public MessageArgumentsFormatter(MethodBodyTransformationContext context) { this.context = context; this.targetMethod = context.TargetElement as MethodDefDeclaration; if (this.targetMethod == null) { throw new InvalidOperationException("Target element is not a method"); } }
private void EmitEqualsObjectOfReferenceType(InstructionWriter writer, IType genericTypeInstance, MethodDefDeclaration typedEqualsMethod, CreatedEmptyMethod methodBody) { // Go to typed check. writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionType(OpCodeNumber.Castclass, genericTypeInstance); writer.EmitInstructionMethod(OpCodeNumber.Call, typedEqualsMethod.GetCanonicalGenericInstance()); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, methodBody.ReturnVariable); writer.EmitBranchingInstruction(OpCodeNumber.Br, methodBody.ReturnSequence); }
private void EmitEqualsObjectOfValueType(InstructionWriter writer, IType genericTypeInstance, MethodDefDeclaration typedEqualsMethod, CreatedEmptyMethod methodBody) { // return this.Equals((Typed)other); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionType(OpCodeNumber.Unbox_Any, genericTypeInstance); writer.EmitInstructionMethod(OpCodeNumber.Call, typedEqualsMethod.GetCanonicalGenericInstance()); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, methodBody.ReturnVariable); writer.EmitBranchingInstruction(OpCodeNumber.Br, methodBody.ReturnSequence); }
protected override void ImplementOnSuccess(InstructionBlock block, InstructionWriter writer) { MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration; if (targetMethod == null) { return; } string messageFormatString = this.CreateMessageFormatString(this.onSuccessOptions, targetMethod); this.EmitMessage(block, writer, targetMethod, "Leaving: " + messageFormatString); }
bool FindInitializeCalls(Project project, AssemblyLoaderInfo assemblyLoaderInfo) { INamedType packerUtilityType = (INamedType)project.Module.FindType(typeof(PackerUtility)); MethodDefDeclaration packerUtilityInitialize = project.Module.FindMethod(packerUtilityType, "Initialize").GetMethodDefinition(); Sdk.CodeWeaver.Weaver weaver = new Sdk.CodeWeaver.Weaver(project); ReplacePackerUtilityInitializeAdvice replacingAdvice = new ReplacePackerUtilityInitializeAdvice(assemblyLoaderInfo.AttachMethod); weaver.AddMethodLevelAdvice(replacingAdvice, null, JoinPointKinds.InsteadOfCall, new[] { packerUtilityInitialize }); weaver.Weave(); return(replacingAdvice.ReplacedAtLeastOneCall); }
private void AddCollectionCode(FieldDefDeclaration field, InstructionWriter writer, LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType) { if (field.FieldType.IsValueTypeSafe() == true) { AddCollectionCodeInternal(field, resultVariable, method, enhancedType, writer); } else { LoadVariable(field, writer); writer.IfNotZero( thenw => { AddCollectionCodeInternal(field, resultVariable, method, enhancedType, thenw); }, elsew => { }); } }
private void AddCollectionCodeInternal(FieldDefDeclaration field, LocalVariableSymbol resultVariable, MethodDefDeclaration method, TypeDefDeclaration enhancedType, InstructionWriter writer) { LoadVariable(field, writer); var enumeratorVariable = method.MethodBody.RootInstructionBlock.DefineLocalVariable(IEnumeratorType, "enumeratorVariable"); var currentVariable = method.MethodBody.RootInstructionBlock.DefineLocalVariable( method.Module.Cache.GetIntrinsic(IntrinsicType.Object), "enumeratorObject"); AddGetEnumerator(writer, enumeratorVariable, field); AddCollectionLoop(resultVariable, writer, enumeratorVariable, currentVariable); }
private string CreateMessageFormatString(LogOptions logOption, MethodDefDeclaration targetMethod) { StringBuilder formatBuilder = new StringBuilder(); formatBuilder.AppendFormat("{0}.{1}", targetMethod.DeclaringType, targetMethod.Name); formatBuilder.Append("("); int parameterCount = Context.MethodMapping.MethodSignature.ParameterCount; for (int i = 0; i < parameterCount; i++) { if (i > 0) { formatBuilder.Append(", "); } ITypeSignature parameterType = Context.MethodMapping.MethodSignature.GetParameterType(i); if ((logOption & LogOptions.IncludeParameterType) != 0) { formatBuilder.Append(parameterType.ToString()); formatBuilder.Append(' '); } if ((logOption & LogOptions.IncludeParameterName) != 0) { formatBuilder.Append(Context.MethodMapping.MethodMappingInformation.GetParameterName(i)); formatBuilder.Append(' '); } if ((logOption & LogOptions.IncludeParameterValue) != 0) { formatBuilder.AppendFormat("= "); if (IntrinsicTypeSignature.Is(parameterType, IntrinsicType.String)) { formatBuilder.AppendFormat("\"" + "{{{0}}}" + "\"", i); } else { formatBuilder.AppendFormat("{{{0}}}", i); } } } formatBuilder.Append(")"); return(formatBuilder.ToString()); }
public override void CompileTimeValidate(MethodDefDeclaration method, IMessageSink messages) { base.CompileTimeValidate(method, messages); if (exception != null) { if (!ValidateExceptionTypeIsException(messages)) { return; } if (!ValidateExceptionTypeCanBeInstantiated(messages)) { return; } } }
private void ReplaceOperator(TypeDefDeclaration enhancedType, MethodDefDeclaration equalityMethodDef, bool negate) { InstructionBlock originalCode = equalityMethodDef.MethodBody.RootInstructionBlock; originalCode.Detach(); InstructionBlock root = equalityMethodDef.MethodBody.CreateInstructionBlock(); equalityMethodDef.MethodBody.RootInstructionBlock = root; var newSequence = root.AddInstructionSequence(); using (var writer = InstructionWriter.GetInstance()) { writer.AttachInstructionSequence(newSequence); if (enhancedType.IsValueType()) { var canonicalType = enhancedType.GetCanonicalGenericInstance(); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionType(OpCodeNumber.Box, canonicalType); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionType(OpCodeNumber.Box, canonicalType); } else { writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); } writer.EmitInstructionMethod(OpCodeNumber.Call, this.staticEqualsMethod); if (negate) { writer.EmitInstruction(OpCodeNumber.Ldc_I4_0); writer.EmitInstruction(OpCodeNumber.Ceq); } writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); } }
private TypeDefDeclaration CreateContainingType() { string uniqueName = this.module.Types.GetUniqueName( DebuggerSpecialNames.GetDeclarationSpecialName("LoggingImplementationDetails{0}")); TypeDefDeclaration logCategoriesType = new TypeDefDeclaration { Name = uniqueName, Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.Abstract, BaseType = ((IType)this.module.Cache.GetType("System.Object, mscorlib")) }; this.module.Types.Add(logCategoriesType); // Add [CompilerGenerated] and [DebuggerNonUserCode] to the type this.weavingHelper.AddCompilerGeneratedAttribute(logCategoriesType.CustomAttributes); this.weavingHelper.AddDebuggerNonUserCodeAttribute(logCategoriesType.CustomAttributes); MethodDefDeclaration staticConstructor = new MethodDefDeclaration { Name = ".cctor", Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, }; logCategoriesType.Methods.Add(staticConstructor); staticConstructor.ReturnParameter = new ParameterDeclaration { Attributes = ParameterAttributes.Retval, ParameterType = this.module.Cache.GetIntrinsic(IntrinsicType.Void) }; this.constructorBlock = staticConstructor.MethodBody.RootInstructionBlock = staticConstructor.MethodBody.CreateInstructionBlock(); this.returnSequence = staticConstructor.MethodBody.RootInstructionBlock.AddInstructionSequence(null, NodePosition.After, null); this.writer.AttachInstructionSequence(this.returnSequence); this.writer.EmitInstruction(OpCodeNumber.Ret); this.writer.DetachInstructionSequence(); return(logCategoriesType); }
public MethodTreeNode(MethodDefDeclaration method) : base(method, TreeViewImage.Method, method.Visibility) { this.method = method; StringBuilder name = new StringBuilder(255); this.method = method; name.Append(method.Name); bool first = true; if (method.Parameters.Count > 0) { name.Append("("); foreach (ParameterDeclaration parameter in method.Parameters) { if (!first) { name.Append(", "); } else { name.Append(' '); first = false; } name.Append(parameter.ParameterType.ToString()); name.Append(' '); name.Append(parameter.Name); } name.Append(" )"); } name.Append(" : "); name.Append(method.ReturnParameter.ParameterType.ToString()); this.Text = name.ToString(); this.EnableLatePopulate(); }
protected override void CompileTimeValidateParameters(MethodDefDeclaration method, IMessageSink messages, ParameterDeclaration firstParameter, ParameterDeclaration secondParameter) { base.CompileTimeValidateParameters(method, messages, firstParameter, secondParameter); if(typeof(IComparable).IsAssignableFrom(firstParameter.ParameterType.GetSystemType(null, null))) { firstParameterIsComparable = true; } else if(typeof(IComparable).IsAssignableFrom(secondParameter.ParameterType.GetSystemType(null, null))) { firstParameterIsComparable = false; } else { messages.Write(new Message( SeverityType.Error, "ComparisonValidatorAttribute_ParametersCantBeCompared", string.Format(CultureInfo.InvariantCulture, "None of the parameters '{0}' and '{1}' implements IComparable.", firstParameter.Name, secondParameter.Name), GetType().FullName )); } }
public MethodTreeNode( MethodDefDeclaration method ) : base( method, TreeViewImage.Method, method.Visibility ) { this.method = method; StringBuilder name = new StringBuilder( 255 ); this.method = method; name.Append( method.Name ); bool first = true; if ( method.Parameters.Count > 0 ) { name.Append( "(" ); foreach ( ParameterDeclaration parameter in method.Parameters ) { if ( !first ) { name.Append( ", " ); } else { name.Append( ' ' ); first = false; } name.Append( parameter.ParameterType.ToString() ); name.Append( ' ' ); name.Append( parameter.Name ); } name.Append( " )" ); } name.Append( " : " ); name.Append( method.ReturnParameter.ParameterType.ToString() ); this.Text = name.ToString(); this.EnableLatePopulate(); }
private static void GetPropertyAccessorDefinitions(PropertyDeclaration propertyDeclaration, out MethodDefDeclaration getMethodDef, out MethodDefDeclaration setMethodDef) { getMethodDef = null; setMethodDef = null; foreach (MethodSemanticDeclaration methodSemanticDef in propertyDeclaration.Members) { MethodDefDeclaration methodDef = methodSemanticDef.Method; if (methodDef.Name.StartsWith("get_")) { getMethodDef = methodDef; } else if (methodDef.Name.StartsWith("set_")) { setMethodDef = methodDef; } else { throw new InvalidOperationException("Found a NotifyPropertyChanged attribute on something other than a property"); } } }
public override bool Execute() { var consoleWriteLine = FindConsoleWriteLine(); var enumerator = annotationRepositoryService.GetAnnotationsOfType(typeof(HelloWorldAttribute), false, false); while (enumerator.MoveNext()) { // Iterates over declarations to which our attribute has been applied. If the attribute weren't // a MulticastAttribute, that would be just the declarations that it annotates. With multicasting, it // can be far more declarations. MetadataDeclaration targetDeclaration = enumerator.Current.TargetElement; // Multicasting ensures that our attribute is only applied to methods, so there is little chance of // a class cast error here: MethodDefDeclaration targetMethod = (MethodDefDeclaration)targetDeclaration; AddHelloWorldToMethod(targetMethod, consoleWriteLine); } return(true); }
private TypeDefDeclaration CreateContainingType() { string uniqueName = this.module.Types.GetUniqueName( DebuggerSpecialNames.GetDeclarationSpecialName("LoggingImplementationDetails{0}")); TypeDefDeclaration logCategoriesType = new TypeDefDeclaration { Name = uniqueName, Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.Abstract, BaseType = ((IType)this.module.Cache.GetType("System.Object, mscorlib")) }; this.module.Types.Add(logCategoriesType); // Add [CompilerGenerated] and [DebuggerNonUserCode] to the type this.weavingHelper.AddCompilerGeneratedAttribute(logCategoriesType.CustomAttributes); this.weavingHelper.AddDebuggerNonUserCodeAttribute(logCategoriesType.CustomAttributes); MethodDefDeclaration staticConstructor = new MethodDefDeclaration { Name = ".cctor", Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName | MethodAttributes.HideBySig, }; logCategoriesType.Methods.Add(staticConstructor); staticConstructor.ReturnParameter = new ParameterDeclaration { Attributes = ParameterAttributes.Retval, ParameterType = this.module.Cache.GetIntrinsic(IntrinsicType.Void) }; this.constructorBlock = staticConstructor.MethodBody.RootInstructionBlock = staticConstructor.MethodBody.CreateInstructionBlock(); this.returnSequence = staticConstructor.MethodBody.RootInstructionBlock.AddInstructionSequence(null, NodePosition.After, null); this.writer.AttachInstructionSequence(this.returnSequence); this.writer.EmitInstruction(OpCodeNumber.Ret); this.writer.DetachInstructionSequence(); return logCategoriesType; }
public ParameterCollectionTreeNode(MethodDefDeclaration declaration) : base(TreeViewImage.Folder, null) { this.declaration = declaration; this.Text = "Parameters"; this.EnableLatePopulate(); }
public override void Implement(MethodBodyTransformationContext context) { /* We want to generate the following * if ( !this.<>4__this.Dispatcher.CheckAccess() ) * { * SynchronizationContext oldContext = SynchronizationContext.Current; * SynchronizationContext.SetSynchronizationContext( this.<>4__this.Dispatcher.SynchronizationContext ); * this.<>t__dispatchAwaiter = Task.Yield().GetAwaiter(); * this.<>t__builder.AwaitUnsafeOnCompleted<YieldAwaitable.YieldAwaiter, Player.<Ping>d__2>(ref this.<>t__dispatchAwaiter, ref this); * SynchronizationContext.SetSynchronizationContext( oldContext ); * return; * } * */ MethodDefDeclaration targetMethod = (MethodDefDeclaration)context.TargetElement; TypeDefDeclaration targetType = targetMethod.DeclaringType; targetMethod.MethodBody.MaxStack = -1; // Add the field where we will store the awaiter. FieldDefDeclaration awaiterFieldDef = new FieldDefDeclaration { Name = "<>t__dispatchAwaiter", FieldType = this.parent.yieldAwaiter_Type, Attributes = FieldAttributes.Private }; targetType.Fields.Add(awaiterFieldDef); IField awaiterField = awaiterFieldDef.GetCanonicalGenericInstance(); // Find other fields. IField thisField = targetType.Fields.Single <FieldDefDeclaration>(f => f.Name.EndsWith("__this")).GetCanonicalGenericInstance(); IField builderField = targetType.Fields.GetByName("<>t__builder").GetCanonicalGenericInstance(); // Emit instructions. InstructionBlock myBlock = context.InstructionBlock.AddChildBlock(null, NodePosition.After, null); InstructionBlock theirBlock = context.InstructionBlock.AddChildBlock(null, NodePosition.After, null); LocalVariableSymbol awaitableLocal = myBlock.DefineLocalVariable(this.parent.task_Yield_Method.ReturnType, "awaitable"); LocalVariableSymbol synchronizationContextLocal = myBlock.DefineLocalVariable(this.parent.synchronizationContext_Type, "oldContext"); InstructionSequence entrySequence = myBlock.AddInstructionSequence(null, NodePosition.After, null); InstructionSequence exitSequence = myBlock.AddInstructionSequence(null, NodePosition.After, null); InstructionWriter writer = new InstructionWriter(); writer.AttachInstructionSequence(entrySequence); // Emit: if ( this.<>4__this.Dispatcher.CheckAccess() ) goto exitSequence; writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, thisField); writer.EmitInstructionMethod(OpCodeNumber.Call, this.parent.actor_GetDispatcher_Method); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.parent.dispatcher_CheckAccess_Method); writer.EmitBranchingInstruction(OpCodeNumber.Brtrue, exitSequence); // Emit: this.<>t__dispatchAwaiter = Task.Yield().GetAwaiter() writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionMethod(OpCodeNumber.Call, this.parent.task_Yield_Method); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, awaitableLocal); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloca, awaitableLocal); writer.EmitInstructionMethod(OpCodeNumber.Call, this.parent.yieldAwaitable_GetAwaiter_Method); writer.EmitInstructionField(OpCodeNumber.Stfld, awaiterField); // Emit: oldContext = SynchronizationContext.Current writer.EmitInstructionMethod(OpCodeNumber.Call, this.parent.synchronizationContext_getCurrent_Method); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, synchronizationContextLocal); // Emit: SynchronizationContext.SetSynchronizationContext(this.<>4__this.Dispatcher.SynchronizationContext) writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, thisField); writer.EmitInstructionMethod(OpCodeNumber.Call, this.parent.actor_GetDispatcher_Method); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, this.parent.dispatcher_getSynchronizationContext_Method); writer.EmitInstructionMethod(OpCodeNumber.Call, this.parent.synchronizationContext_SetSynchronizationContext_Method); // Choose which AwaitUnsafeOnCompleted method to call. IGenericMethodDefinition awaitUnsafeOnCompletedMethod; ITypeSignature[] awaitUnsafeOnCompletedGenericTypeParameters; if (builderField.FieldType == this.parent.asyncVoidMethodBuilder_Type) { awaitUnsafeOnCompletedMethod = this.parent.asyncVoidMethodBuilder_AwaitUnsafeOnCompleted_Method; awaitUnsafeOnCompletedGenericTypeParameters = null; } else if (builderField.FieldType == this.parent.asyncTaskMethodBuilder_Type) { awaitUnsafeOnCompletedMethod = this.parent.asyncTaskMethodBuilder_AwaitUnsafeOnCompleted_Method; awaitUnsafeOnCompletedGenericTypeParameters = null; } else { // This is a generic task. awaitUnsafeOnCompletedMethod = this.parent.asyncTaskMethodBuilderGeneric_AwaitUnsafeOnCompleted_Method; awaitUnsafeOnCompletedGenericTypeParameters = builderField.FieldType.GetGenericContext(GenericContextOptions.None).GetGenericTypeParameters(); } IMethod awaitUnsafeOnCompletedGenericMethod = awaitUnsafeOnCompletedMethod.GetGenericInstance(new GenericMap(awaitUnsafeOnCompletedGenericTypeParameters, new ITypeSignature[] { this.parent.yieldAwaiter_Type, targetType.GetCanonicalGenericInstance() })); // Emit: this.<>t__builder.AwaitUnsafeOnCompleted<YieldAwaitable.YieldAwaiter, Player.<Ping>d__2>(ref this.<>t__dispatchAwaiter, ref this); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldflda, builderField); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldflda, awaiterField); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionMethod(OpCodeNumber.Call, awaitUnsafeOnCompletedGenericMethod); // Emit: SynchronizationContext.SetSynchronizationContext( oldContext ); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, synchronizationContextLocal); writer.EmitInstructionMethod(OpCodeNumber.Call, this.parent.synchronizationContext_SetSynchronizationContext_Method); writer.EmitBranchingInstruction(OpCodeNumber.Leave, context.LeaveBranchTarget); writer.DetachInstructionSequence(); // We are done. Give the pipeline to the next node. context.AddRedirection(theirBlock, context.LeaveBranchTarget); }
private MethodDefDeclaration InjectEqualsType(TypeDefDeclaration enhancedType, StructuralEqualityAttribute config, ICollection <FieldDefDeclaration> ignoredFields) { IType genericTypeInstance = enhancedType.GetCanonicalGenericInstance(); var existingMethod = enhancedType.Methods.FirstOrDefault <IMethod>(declaration => { return(declaration.Name == "Equals" && declaration.IsPublic() && !declaration.IsStatic && declaration.ParameterCount == 1 && declaration.GetParameterType(0).Equals(genericTypeInstance)); }); if (existingMethod != null) { return(existingMethod.GetMethodDefinition()); } // public virtual bool Equals( Typed other ) var equalsDeclaration = new MethodDefDeclaration { Name = "Equals", Attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, CallingConvention = CallingConvention.HasThis }; enhancedType.Methods.Add(equalsDeclaration); equalsDeclaration.Parameters.Add(new ParameterDeclaration(0, "other", genericTypeInstance)); equalsDeclaration.ReturnParameter = ParameterDeclaration.CreateReturnParameter(this.booleanType); CompilerGeneratedAttributeHelper.AddCompilerGeneratedAttribute(equalsDeclaration); using (var writer = InstructionWriter.GetInstance()) { var methodBody = MethodBodyCreator.CreateModifiableMethodBody(writer, equalsDeclaration); writer.AttachInstructionSequence(methodBody.PrincipalBlock.AddInstructionSequence()); writer.EmitInstruction(OpCodeNumber.Ldc_I4_0); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, methodBody.ReturnVariable); this.InjectReferenceEquals(writer, methodBody, enhancedType); // Writer is either attached to the same sequence (value types) or to a new one which should check the structure. // return base.Equals(other) && this.field1 == other.field1 && ...; if (!config.IgnoreBaseClass && enhancedType.IsValueTypeSafe() != true) { // Find the base method. var baseEqualsMethod = this.instanceEqualsMethod.FindOverride(enhancedType.BaseTypeDef, true) .GetInstance(enhancedType.Module, enhancedType.BaseType.GetGenericContext()); // Do not invoke object.Equals(); if (baseEqualsMethod.DeclaringType.GetTypeDefinition() != this.objectTypeDef) { writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionMethod(OpCodeNumber.Call, baseEqualsMethod); // base.Equals(other) returned false, go to return. writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, methodBody.ReturnSequence); } } foreach (var field in GetFieldsForComparison(enhancedType, ignoredFields)) { this.EmitEqualsField(writer, methodBody, field); } InjectCustomMethods(enhancedType, writer, methodBody); // return true; writer.EmitInstruction(OpCodeNumber.Ldc_I4_1); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, methodBody.ReturnVariable); writer.EmitBranchingInstruction(OpCodeNumber.Br, methodBody.ReturnSequence); writer.DetachInstructionSequence(); } return(equalsDeclaration); }
/// <summary> /// Finds a method with the same signature in the class /// </summary> /// <param name="decl">Class to inspect</param> /// <param name="method">Method with a name and signature</param> /// <returns>Found method or null</returns> public static MethodDefDeclaration FindSameMethod([NotNull] TypeDefDeclaration decl, [NotNull] MethodDefDeclaration method) { IMethod found = decl.Methods.GetMethod( method.Name, method, BindingOptions.OnlyExisting); if (found == null) { return(null); } return(found.GetMethodDefinition(BindingOptions.OnlyExisting)); }
/// <summary> /// Initializes a new instance of the <see cref="BuildParameterCollectionAdvice"/> class. /// </summary> /// <param name="method">The method.</param> public BuildParameterCollectionAdvice(MethodDefDeclaration method) { this.method = method; }
public virtual void CompileTimeValidate(MethodDefDeclaration method, IMessageSink messages) { }
/// <summary> /// Creates token for the specified placeholder. /// </summary> /// <param name="placeholder">Placeholder to create token for.</param> /// <param name="target">List to appent the token to.</param> /// <param name="wovenMethod">Method being woven.</param> /// <exception cref="ArgumentNullException"><paramref name="placeholder"/>, <paramref name="target"/> or <paramref name="wovenMethod"/> is <see langword="null"/>.</exception> /// <exception cref="FormatException"><paramref name="placeholder"/> is invalid or unrecognized placeholder.</exception> private static void ProcessPlaceholder(string placeholder, ICollection<IMessageToken> target, MethodDefDeclaration wovenMethod) { if (placeholder == null) { throw new ArgumentNullException("placeholder"); } if (target == null) { throw new ArgumentNullException("target"); } if (wovenMethod == null) { throw new ArgumentNullException("wovenMethod"); } if (string.Equals(placeholder, signaturePlaceholder2, StringComparison.InvariantCulture) || string.Equals(placeholder, signaturePlaceholder1, StringComparison.InvariantCulture)) { target.Add(new FixedToken(GetMethodSignature(wovenMethod))); } else if (placeholder.StartsWith(parameterPrefix, StringComparison.InvariantCulture)) { // Extract the name of the parameter. string parameterName = placeholder.Substring(parameterPrefix.Length); ParameterDeclaration referredParameter = null; foreach (ParameterDeclaration parameter in wovenMethod.Parameters) { if (string.Equals(parameter.Name, parameterName, StringComparison.InvariantCulture)) { referredParameter = parameter; break; } } if (referredParameter == null) { throw new FormatException(string.Format(CultureInfo.CurrentCulture, "Invalid parameter name: {0}.", parameterName)); } target.Add(new ParameterValueToken(referredParameter)); } else if (string.Equals(placeholder, shortParameterList, StringComparison.InvariantCulture)) { // Check if the method has any parameters. if (wovenMethod.Parameters.Count > 0) { // Add opening quote for the first parameter. target.Add(new FixedToken(@"""")); bool isFirstParameter = true; foreach (ParameterDeclaration parameter in wovenMethod.Parameters) { // Do not prepend anything before the first parameter. if (! isFirstParameter) { // Add closing quote for the previous parameter, then comma, then opening quote for the current parameter. target.Add(new FixedToken(@""", """)); } // Append parameter value. target.Add(new ParameterValueToken(parameter)); // Next parameter is not the first one. isFirstParameter = false; } // Add closing quote for the last parameter. target.Add(new FixedToken(@"""")); } } else if (string.Equals(placeholder, returnValue, StringComparison.InvariantCulture)) { target.Add(new ReturnValueToken(wovenMethod.ReturnParameter)); } else { throw new FormatException(string.Format(CultureInfo.CurrentCulture, "Unknown placeholder in template: {0}.", placeholder)); } }
protected virtual void CompileTimeValidateParameters(MethodDefDeclaration method, IMessageSink messages, ParameterDeclaration firstParameter, ParameterDeclaration secondParameter) { }
public override void Implement(TransformationContext context) { ModuleDeclaration module = this.AspectWeaver.Module; TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "AutoGeneratedValidate", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence(sequence); // Find the base method. IMethod baseValidateMethod = null; IType baseTypeCursor = typeDef.BaseType; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new ITypeSignature[0], 0); while (baseValidateMethod == null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseValidateMethod = baseTypeCursorTypeDef.Methods.GetMethod("AutoGeneratedValidate", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } // TODO: support generic base types. // Call the base method. writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseValidateMethod.Translate(typeDef.Module)); // Make an array with the boxed field values. TypeValidationAspect aspect = (TypeValidationAspect)this.AspectWeaverInstance.Aspect; LocalVariableSymbol fieldValuesArrayLocal = instructionBlock.DefineLocalVariable( module.Cache.GetType(typeof(object[])), "fieldValues"); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, aspect.Validators.Count); writer.EmitInstructionType(OpCodeNumber.Newarr, module.Cache.GetIntrinsic(IntrinsicType.Object)); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, fieldValuesArrayLocal); int i = 0; foreach (FieldValidationAttribute validator in aspect.Validators) { FieldDefDeclaration fieldDef = typeDef.Fields.GetByName(validator.TargetLocation.Name); IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, i); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); writer.EmitConvertToObject(fieldSpec.FieldType); writer.EmitInstruction(OpCodeNumber.Stelem_Ref); i++; } // Get the validator method. IMethod validateMethod = module.Cache.GetItem( () => module.FindMethod( typeof(TypeValidationAspect).GetMethod("Validate"), BindingOptions.Default)); // Call the validator. this.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField(writer, null); writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, fieldValuesArrayLocal); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, validateMethod); writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); } }
public BeforeOnDeserializingMethodAdvice( MethodDefDeclaration onDeserializingMethodDef, MethodDefDeclaration initializeMethodDef ) { this.Method = onDeserializingMethodDef; this.initializeMethodDef = initializeMethodDef; }
public void AddGetHashCodeTo(TypeDefDeclaration enhancedType, StructuralEqualityAttribute config, ISet <FieldDefDeclaration> ignoredFields) { if (enhancedType.Methods.Any <IMethod>(m => m.Name == "GetHashCode" && m.ParameterCount == 0)) { // GetHashCode already present, just keep it. return; } // Create signature MethodDefDeclaration method = new MethodDefDeclaration { Name = "GetHashCode", CallingConvention = CallingConvention.HasThis, Attributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig }; enhancedType.Methods.Add(method); CompilerGeneratedAttributeHelper.AddCompilerGeneratedAttribute(method); method.ReturnParameter = ParameterDeclaration.CreateReturnParameter(enhancedType.Module.Cache.GetIntrinsic(IntrinsicType.Int32)); // Generate ReSharper-style Fowler–Noll–Vo hash: using (InstructionWriter writer = InstructionWriter.GetInstance()) { CreatedEmptyMethod getHashCodeData = MethodBodyCreator.CreateModifiableMethodBody(writer, method); var resultVariable = getHashCodeData.ReturnVariable; writer.AttachInstructionSequence(getHashCodeData.PrincipalBlock.AddInstructionSequence()); // Start with 0 writer.EmitInstruction(OpCodeNumber.Ldc_I4_0); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable); bool first = true; // Add base.GetHashCode(): if (!config.IgnoreBaseClass) { bool ignorable = enhancedType.BaseTypeDef.Name == "System.Object" || enhancedType.IsValueTypeSafe() == true; if (!ignorable) { var baseHashCode = project.Module.FindMethod(enhancedType.BaseTypeDef, "GetHashCode", BindingOptions.DontThrowException, 0); // TODO Gael says: using FindOverride would be better if (baseHashCode != null) { writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable); writer.EmitInstruction(OpCodeNumber.Ldarg_0); // TODO what if it is two steps removed? then we won't call it! writer.EmitInstructionMethod(OpCodeNumber.Call, baseHashCode.GetGenericInstance(enhancedType.BaseType.GetGenericContext())); writer.EmitInstruction(OpCodeNumber.Add); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable); first = false; } } } // For each field, do "hash = hash * 397 ^ field?.GetHashCode(); foreach (FieldDefDeclaration field in enhancedType.Fields) { if (field.IsConst || field.IsStatic || ignoredFields.Contains(field)) { continue; } this.AddFieldCode(field, first, writer, resultVariable, method, enhancedType); first = false; } // Now custom logic: foreach (var customLogic in enhancedType.Methods) { if (customLogic.CustomAttributes.GetOneByType(typeof(AdditionalGetHashCodeMethodAttribute) .FullName) != null) { writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, resultVariable); writer.EmitInstructionInt32(OpCodeNumber.Ldc_I4, magicNumber); writer.EmitInstruction(OpCodeNumber.Mul); AddCustomLogicCall(enhancedType, writer, customLogic); writer.EmitInstruction(OpCodeNumber.Xor); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, resultVariable); } } // Return the hash: writer.EmitBranchingInstruction(OpCodeNumber.Br, getHashCodeData.ReturnSequence); writer.DetachInstructionSequence(); } }
private bool MethodContainsSerializationAttribute(MethodDefDeclaration method, string simpleName) { return(method.CustomAttributes.GetOneByType("System.Runtime.Serialization." + simpleName) != null); }
/// <summary> /// Creates a new method body and assigns it to <paramref name="hostMethod"/>. The method body looks as described in <see cref="CreatedEmptyMethod"/>. /// </summary> /// <param name="instructionWriter">A <b>detached</b> instruction writer.</param> /// <param name="hostMethod">The method without body. The body will be assigned to this method.</param> /// <returns>References to points in the method body.</returns> public static CreatedEmptyMethod CreateModifiableMethodBody(InstructionWriter instructionWriter, MethodDefDeclaration hostMethod) { // Create a new method body to host the pipeline. hostMethod.MethodBody = new MethodBodyDeclaration(); InstructionBlock rootInstructionBlock = hostMethod.MethodBody.RootInstructionBlock = hostMethod.MethodBody.CreateInstructionBlock(); InstructionBlock sequencePointBlock = rootInstructionBlock.AddChildBlock(); InstructionSequence sequencePointSequence = sequencePointBlock.AddInstructionSequence(); instructionWriter.AttachInstructionSequence(sequencePointSequence); instructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); instructionWriter.EmitInstruction(OpCodeNumber.Nop); instructionWriter.DetachInstructionSequence(); InstructionBlock implementationBlock = rootInstructionBlock.AddChildBlock(); InstructionBlock returnBlock = rootInstructionBlock.AddChildBlock(); InstructionSequence returnSequence = returnBlock.AddInstructionSequence(); instructionWriter.AttachInstructionSequence(returnSequence); instructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden); LocalVariableSymbol returnVariable; if (!hostMethod.ReturnParameter.ParameterType.IsIntrinsic(IntrinsicType.Void)) { hostMethod.MethodBody.InitLocalVariables = true; returnVariable = rootInstructionBlock.DefineLocalVariable( hostMethod.ReturnParameter.ParameterType, DebuggerSpecialNames.GetVariableSpecialName(hostMethod.Domain, "returnValue", DebuggerSpecialVariableKind.ReturnValue) ); instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, returnVariable); } else { returnVariable = null; } instructionWriter.EmitInstruction(OpCodeNumber.Ret); instructionWriter.DetachInstructionSequence(); return(new CreatedEmptyMethod(hostMethod, implementationBlock, returnVariable, returnSequence)); }
private bool ShouldUseWrapper(MethodDefDeclaration targetMethod) { if (targetMethod.Name == "ToString") { MethodDefDeclaration parent = targetMethod.GetParentDefinition(true); if (parent != null) { if (parent.MatchesReference( this.transformationInstance.parent.assets.ToStringMethodSignature)) { return true; } } } for (int i = 0; i < targetMethod.Parameters.Count; i++) { ITypeSignature parameterType = targetMethod.Parameters[i].ParameterType; if (!parameterType.BelongsToClassification(TypeClassifications.Intrinsic) || IntrinsicTypeSignature.Is(parameterType, IntrinsicType.Object)) { return true; } } return false; }
private void EmitWrapperCallBody(MethodDefDeclaration wrapperMethod, IMethod loggerMethod) { InstructionBlock rootBlock = wrapperMethod.MethodBody.CreateInstructionBlock(); wrapperMethod.MethodBody.RootInstructionBlock = rootBlock; InstructionBlock parentBlock = rootBlock.AddChildBlock(null, NodePosition.After, null); InstructionBlock tryBlock = rootBlock.AddChildBlock(null, NodePosition.After, null); InstructionBlock leaveTryBlock = rootBlock.AddChildBlock(null, NodePosition.After, null); InstructionSequence sequence = parentBlock.AddInstructionSequence(null, NodePosition.After, null); // set isLogging to true this.writer.AttachInstructionSequence(sequence); this.writer.EmitInstruction(OpCodeNumber.Ldc_I4_1); this.writer.EmitInstructionField(OpCodeNumber.Stsfld, this.isLoggingField); this.writer.DetachInstructionSequence(); // if isLogging is true, return InstructionSequence branchSequence = parentBlock.AddInstructionSequence(null, NodePosition.Before, null); this.writer.AttachInstructionSequence(branchSequence); this.writer.EmitInstructionField(OpCodeNumber.Ldsfld, this.isLoggingField); this.writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, sequence); this.writer.EmitInstruction(OpCodeNumber.Ret); this.writer.DetachInstructionSequence(); // return instruction at the end of the method InstructionSequence retSequence = leaveTryBlock.AddInstructionSequence(null, NodePosition.After, null); this.writer.AttachInstructionSequence(retSequence); this.writer.EmitInstruction(OpCodeNumber.Ret); this.writer.DetachInstructionSequence(); InstructionSequence trySequence = tryBlock.AddInstructionSequence(null, NodePosition.After, null); this.writer.AttachInstructionSequence(trySequence); for (int i = 0; i < wrapperMethod.Parameters.Count; i++) { writer.EmitInstructionInt16(OpCodeNumber.Ldarg, (short)i); } this.EmitCallHandler(loggerMethod); this.writer.DetachInstructionSequence(); InstructionSequence leaveSequence = tryBlock.AddInstructionSequence(null, NodePosition.After, null); this.writer.AttachInstructionSequence(leaveSequence); this.writer.EmitBranchingInstruction(OpCodeNumber.Leave, retSequence); this.writer.DetachInstructionSequence(); InstructionBlock protectedBlock; InstructionBlock[] catchBlocks; InstructionBlock finallyBlock; this.weavingHelper.AddExceptionHandlers(this.writer, tryBlock, leaveSequence, null, true, out protectedBlock, out catchBlocks, out finallyBlock); InstructionSequence finallySequence = finallyBlock.AddInstructionSequence(null, NodePosition.After, null); this.writer.AttachInstructionSequence(finallySequence); this.writer.EmitInstruction(OpCodeNumber.Ldc_I4_0); this.writer.EmitInstructionField(OpCodeNumber.Stsfld, this.isLoggingField); //this.writer.EmitInstruction(OpCodeNumber.Endfinally); this.writer.DetachInstructionSequence(); }
private static void ImplementSetter( PropertyDeclaration property, TypeDefDeclaration type, IField field, MethodAttributes methodAttributes, CustomAttributeDeclaration compilerGenerated) { // Implement setter var setter = new MethodDefDeclaration { Attributes = methodAttributes, Name = "set_" + property.Name, CallingConvention = CallingConvention.HasThis, }; type.Methods.Add(setter); MarkCompilerGenerated(setter, compilerGenerated); setter.ReturnParameter = new ParameterDeclaration { ParameterType = type.Module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; setter.Parameters.Add(new ParameterDeclaration(0, "value", property.PropertyType)); var methodBody = new MethodBodyDeclaration(); var sequence = methodBody.CreateInstructionSequence(); var instructionBlock = methodBody.CreateInstructionBlock(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); methodBody.RootInstructionBlock = instructionBlock; setter.MethodBody = methodBody; var writer = new InstructionWriter(); writer.AttachInstructionSequence(sequence); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionField(OpCodeNumber.Stfld, field); writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); property.Members.Add(new MethodSemanticDeclaration(MethodSemantics.Setter, setter)); }
/// <summary> /// Remove a method from a class /// </summary> public static void RemoveMethod([NotNull] ref TypeDefDeclaration decl, [NotNull] MethodDefDeclaration method) { decl.Methods.Remove(method); }
public MethodDefDeclaration GetTraceStringFormatMethod() { return(this.traceWriteLineWrapperMethod ?? (this.traceWriteLineWrapperMethod = this.CreateTraceStringFormatWrapper("TraceWriteLineFormat"))); }
private void EmitMessage(InstructionBlock block, InstructionWriter writer, MethodDefDeclaration targetMethod, string messageFormatString) { // TODO: nested types string category = targetMethod.DeclaringType.Name; ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category); InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null); writer.AttachInstructionSequence(sequence); if (builder.SupportsIsEnabled) { builder.EmitGetIsEnabled(writer, LogSeverity.Trace); InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence); } int parameterCount = Context.MethodMapping.MethodSignature.ParameterCount; bool hasThis = Context.MethodMapping.MethodSignature.CallingConvention == CallingConvention.HasThis; builder.EmitWrite(writer, block, messageFormatString, parameterCount, LogSeverity.Trace, null, (i, instructionWriter) => { instructionWriter.EmitInstructionInt16(OpCodeNumber.Ldarg, (short)(hasThis ? i + 1 : i)); instructionWriter.EmitConvertToObject( this.Context.MethodMapping.MethodSignature.GetParameterType(i)); }); writer.DetachInstructionSequence(); }
/// <summary> /// Yields all the input parameters of the given woven method. /// </summary> /// <param name="wovenMethod">A woven method.</param> /// <remarks> /// Note, that a <c>ref</c> parameter is an input parameter. /// </remarks> private static IEnumerable<ParameterDeclaration> YieldInParameters(MethodDefDeclaration wovenMethod) { foreach (ParameterDeclaration parameter in wovenMethod.Parameters) { if ((parameter.Attributes & (ParameterAttributes.Out | ParameterAttributes.Retval)) == 0) { // Found a parameter, which is neither Out nor Retval. It is an input parameter. // Note, that by ref parameters are also input. yield return parameter; } } }
public override void Implement(TransformationContext context) { ModuleDeclaration module = this.AspectWeaver.Module; TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "AutoGeneratedValidate", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence( sequence ); // Find the base method. IMethod baseValidateMethod = null; IType baseTypeCursor = typeDef.BaseType; MethodSignature methodSignature = new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Void ), new ITypeSignature[0], 0 ); while ( baseValidateMethod == null ) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseValidateMethod = baseTypeCursorTypeDef.Methods.GetMethod( "AutoGeneratedValidate", methodSignature.Translate( baseTypeCursorTypeDef.Module ), BindingOptions.OnlyExisting | BindingOptions.DontThrowException ); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } // TODO: support generic base types. // Call the base method. writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionMethod( OpCodeNumber.Call, (IMethod) baseValidateMethod.Translate( typeDef.Module ) ); // Make an array with the boxed field values. TypeValidationAspect aspect = (TypeValidationAspect) this.AspectWeaverInstance.Aspect; LocalVariableSymbol fieldValuesArrayLocal = instructionBlock.DefineLocalVariable( module.Cache.GetType( typeof(object[]) ), "fieldValues" ); writer.EmitInstructionInt32( OpCodeNumber.Ldc_I4, aspect.Validators.Count ); writer.EmitInstructionType( OpCodeNumber.Newarr, module.Cache.GetIntrinsic( IntrinsicType.Object ) ); writer.EmitInstructionLocalVariable( OpCodeNumber.Stloc, fieldValuesArrayLocal ); int i = 0; foreach ( FieldValidationAttribute validator in aspect.Validators ) { FieldDefDeclaration fieldDef = typeDef.Fields.GetByName( validator.TargetLocation.Name ); IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance( fieldDef ); writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, fieldValuesArrayLocal ); writer.EmitInstructionInt32( OpCodeNumber.Ldc_I4, i ); writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionField( OpCodeNumber.Ldfld, fieldSpec ); writer.EmitConvertToObject( fieldSpec.FieldType ); writer.EmitInstruction( OpCodeNumber.Stelem_Ref ); i++; } // Get the validator method. IMethod validateMethod = module.Cache.GetItem( () => module.FindMethod( typeof(TypeValidationAspect).GetMethod( "Validate" ), BindingOptions.Default ) ); // Call the validator. this.AspectWeaverInstance.AspectRuntimeInstanceField.EmitLoadField( writer, null ); writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, fieldValuesArrayLocal ); writer.EmitInstructionMethod( OpCodeNumber.Callvirt, validateMethod ); writer.EmitInstruction( OpCodeNumber.Ret ); writer.DetachInstructionSequence(); } }
public bool RequiresStackStatus(MethodDefDeclaration method) { return(true); }
public static void ImplementRemoveOn( this EventDeclaration theEvent, TypeDefDeclaration type, IField field, WeavingHelper weavingHelper = null, MethodAttributes methodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Final | MethodAttributes.NewSlot | MethodAttributes.SpecialName) { var module = type.Module; weavingHelper = weavingHelper ?? new WeavingHelper(module); var pEWeavingHelper = module.Cache.GetItem(() => new PostEdgeWeaverAssets(module)); var method = new MethodDefDeclaration { Attributes = methodAttributes, Name = "remove_" + theEvent.Name, CallingConvention = CallingConvention.HasThis }; type.Methods.Add(method); weavingHelper.AddCompilerGeneratedAttribute(method.CustomAttributes); var parameter = new ParameterDeclaration { Name = "value", ParameterType = theEvent.EventType, }; method.Parameters.Add(parameter); var methodBody = new MethodBodyDeclaration(); methodBody.EnsureWritableLocalVariables(); var instructionBlock = methodBody.CreateInstructionBlock(); var initSequence = methodBody.CreateInstructionSequence(); var loopSequence = methodBody.CreateInstructionSequence(); var endSequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(initSequence, NodePosition.After, null); instructionBlock.AddInstructionSequence(loopSequence, NodePosition.After, initSequence); instructionBlock.AddInstructionSequence(endSequence, NodePosition.After, loopSequence); methodBody.RootInstructionBlock = instructionBlock; method.MethodBody = methodBody; methodBody.CreateLocalVariable(theEvent.EventType); methodBody.CreateLocalVariable(theEvent.EventType); methodBody.CreateLocalVariable(theEvent.EventType); methodBody.CreateLocalVariable(module.Cache.GetIntrinsic(typeof(bool))); var writer = new InstructionWriter(); //Initialize writer.AttachInstructionSequence(initSequence); //PropertyChangedHandler handler = this.PropertyChanged writer.EmitInstruction(OpCodeNumber.Ldarg_0); //Get the this pointer writer.EmitInstructionField(OpCodeNumber.Ldfld, field); //Get the event's field writer.EmitInstruction(OpCodeNumber.Stloc_0); //store into the first local variable writer.DetachInstructionSequence(); //Loop //do { writer.AttachInstructionSequence(loopSequence); //PropertyChangedHandler handler2 = handler; writer.EmitInstruction(OpCodeNumber.Ldloc_0); writer.EmitInstruction(OpCodeNumber.Stloc_1); //PropertyChangedHandler handler3 = System.Delegate.Remove(handler2, value) writer.EmitInstruction(OpCodeNumber.Ldloc_1); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionMethod(OpCodeNumber.Call, pEWeavingHelper.DelegateRemoveMethod); writer.EmitInstructionType(OpCodeNumber.Castclass, theEvent.EventType); writer.EmitInstruction(OpCodeNumber.Stloc_2); //handler = System.Threading.Interlocked.CompareExchnage<PropertyChangedEventHandler>(ref this.PropertyChtyChanged, handler3, handler2); var compareExchangeMethodT = pEWeavingHelper.CompareExchangeMethod; var compareExchangeMethod = compareExchangeMethodT.GetGenericInstance(module, theEvent.EventType); writer.EmitInstruction(OpCodeNumber.Ldarg_0); //Load this writer.EmitInstructionField(OpCodeNumber.Ldflda, field); writer.EmitInstruction(OpCodeNumber.Ldloc_2); writer.EmitInstruction(OpCodeNumber.Ldloc_1); writer.EmitInstructionMethod(OpCodeNumber.Call, compareExchangeMethod); writer.EmitInstruction(OpCodeNumber.Stloc_0); //flag = handler != handler2; writer.EmitInstruction(OpCodeNumber.Ldloc_0); writer.EmitInstruction(OpCodeNumber.Ldloc_1); writer.EmitInstruction(OpCodeNumber.Ceq); writer.EmitInstruction(OpCodeNumber.Ldc_I4_0); writer.EmitInstruction(OpCodeNumber.Ceq); writer.EmitInstruction(OpCodeNumber.Stloc_3); //} while (flag); writer.EmitInstruction(OpCodeNumber.Ldloc_3); writer.EmitBranchingInstruction(OpCodeNumber.Brtrue_S, loopSequence); writer.DetachInstructionSequence(); //End writer.AttachInstructionSequence(endSequence); writer.EmitInstruction(OpCodeNumber.Ret); //Exit the method writer.DetachInstructionSequence(); theEvent.Members.Add(new MethodSemanticDeclaration(MethodSemantics.RemoveOn, method)); }
private string CreateMessageFormatString(LogOptions logOption, MethodDefDeclaration targetMethod) { StringBuilder formatBuilder = new StringBuilder(); formatBuilder.AppendFormat("{0}.{1}", targetMethod.DeclaringType, targetMethod.Name); formatBuilder.Append("("); int parameterCount = Context.MethodMapping.MethodSignature.ParameterCount; for (int i = 0; i < parameterCount; i++) { if (i > 0) { formatBuilder.Append(", "); } ITypeSignature parameterType = Context.MethodMapping.MethodSignature.GetParameterType(i); if ((logOption & LogOptions.IncludeParameterType) != 0) { formatBuilder.Append(parameterType.ToString()); formatBuilder.Append(' '); } if ((logOption & LogOptions.IncludeParameterName) != 0) { formatBuilder.Append(Context.MethodMapping.MethodMappingInformation.GetParameterName(i)); formatBuilder.Append(' '); } if ((logOption & LogOptions.IncludeParameterValue) != 0) { formatBuilder.AppendFormat("= "); if (IntrinsicTypeSignature.Is(parameterType, IntrinsicType.String)) { formatBuilder.AppendFormat("\"" + "{{{0}}}" + "\"", i); } else { formatBuilder.AppendFormat("{{{0}}}", i); } } } formatBuilder.Append(")"); return formatBuilder.ToString(); }
public override void Implement( TransformationContext context ) { TypeDefDeclaration typeDef = (TypeDefDeclaration) context.TargetElement; ModuleDeclaration module = this.AspectWeaver.Module; ITypeSignature baseEntityType = module.Cache.GetType( typeof(BaseEntity) ); // Find the base method. IMethod baseCopyToMethod = null; IType baseTypeCursor = typeDef; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new[] { baseEntityType }, 0); while (baseCopyToMethod == null && baseTypeCursor != null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseCopyToMethod = baseTypeCursorTypeDef.Methods.GetMethod("CopyTo", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } if (baseCopyToMethod == null) throw new AssertionFailedException("Could not find a method CopyTo."); if ( baseCopyToMethod.DeclaringType == typeDef ) return; // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "CopyTo", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add( methodDef ); methodDef.CustomAttributes.Add( this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute() ); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic( IntrinsicType.Void ), Attributes = ParameterAttributes.Retval }; ParameterDeclaration cloneParameter = new ParameterDeclaration( 0, "clone", baseEntityType ); methodDef.Parameters.Add( cloneParameter ); // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence( sequence, NodePosition.After, null ); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence( sequence ); // Cast the argument and store it in a local variable. IType typeSpec = GenericHelper.GetTypeCanonicalGenericInstance( typeDef ); LocalVariableSymbol castedCloneLocal = instructionBlock.DefineLocalVariable( typeSpec, "typedClone" ); writer.EmitInstruction( OpCodeNumber.Ldarg_1 ); writer.EmitInstructionType( OpCodeNumber.Castclass, typeSpec ); writer.EmitInstructionLocalVariable( OpCodeNumber.Stloc, castedCloneLocal ); // TODO: support generic base types. // Call the base method. writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstruction( OpCodeNumber.Ldarg_1 ); writer.EmitInstructionMethod( OpCodeNumber.Call, (IMethod) baseCopyToMethod.Translate( typeDef.Module ) ); // Loop on all fields and clone cloneable ones. TypeRefDeclaration cloneableTypeRef = (TypeRefDeclaration) module.Cache.GetType( typeof(ICloneable) ); MethodRefDeclaration cloneMethodRef = (MethodRefDeclaration) cloneableTypeRef.MethodRefs.GetMethod( "Clone", new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Object ), new ITypeSignature[0], 0 ), BindingOptions.Default ); foreach ( FieldDefDeclaration fieldDef in typeDef.Fields ) { if ( (fieldDef.Attributes & FieldAttributes.Static) != 0 ) continue; if ( fieldDef.FieldType == module.Cache.GetIntrinsic( IntrinsicType.String ) ) continue; // Does not work? //bool cloneable = fieldDef.FieldType.Inherits(cloneableTypeRef, GenericMap.Empty); bool cloneable = typeof(ICloneable).IsAssignableFrom( fieldDef.FieldType.GetSystemType( null, null ) ); if ( cloneable ) { IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance( fieldDef ); bool isValueType = fieldSpec.FieldType.BelongsToClassification( TypeClassifications.ValueType ).Equals( NullableBool.True ); InstructionSequence nextSequence = null; if ( !isValueType ) { nextSequence = methodBody.CreateInstructionSequence(); writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionField( OpCodeNumber.Ldfld, fieldSpec ); writer.EmitBranchingInstruction( OpCodeNumber.Brfalse, nextSequence ); } writer.EmitInstructionLocalVariable( OpCodeNumber.Ldloc, castedCloneLocal ); writer.EmitInstruction( OpCodeNumber.Ldarg_0 ); writer.EmitInstructionField( OpCodeNumber.Ldfld, fieldSpec ); if ( isValueType ) { writer.EmitInstructionType( OpCodeNumber.Box, fieldSpec.FieldType ); } //writer.EmitInstructionType(OpCodeNumber.Castclass, cloneableTypeRef); writer.EmitInstructionMethod( OpCodeNumber.Callvirt, cloneMethodRef ); if ( isValueType ) { writer.EmitInstructionType( OpCodeNumber.Unbox, fieldSpec.FieldType ); writer.EmitInstructionType( OpCodeNumber.Ldobj, fieldSpec.FieldType ); } else { writer.EmitInstructionType( OpCodeNumber.Castclass, fieldSpec.FieldType ); } writer.EmitInstructionField( OpCodeNumber.Stfld, fieldSpec ); if ( !isValueType ) { writer.DetachInstructionSequence(); instructionBlock.AddInstructionSequence( nextSequence, NodePosition.After, sequence ); sequence = nextSequence; writer.AttachInstructionSequence( sequence ); } } } writer.EmitInstruction( OpCodeNumber.Ret ); writer.DetachInstructionSequence(); } }
/// <summary> /// Splits the template into the list of tokens. /// </summary> /// <param name="template">Template to find tokens in.</param> /// <param name="wovenMethod">Method being woven.</param> /// <returns>List of tokens in the specified template.</returns> /// <exception cref="ArgumentNullException"><paramref name="template"/> or <paramref name="wovenMethod"/> is <see langword="null"/>.</exception> /// <exception cref="FormatException"><paramref name="template"/> is invalid and cannot be parsed.</exception> public static List<IMessageToken> Tokenize(string template, MethodDefDeclaration wovenMethod, bool includeParamName) { if (template == null) { throw new ArgumentNullException("template"); } if (wovenMethod == null) { throw new ArgumentNullException("wovenMethod"); } // List to put all recognized message parts in. List<IMessageToken> ret = new List<IMessageToken>(); // Algorithm parses the messages by fragments. Boundaries of fragments are special characters, // like sequence indicators. // Position of the first character of the fragment that is currently processed. int fragmentBeginningIndex = 0; while (fragmentBeginningIndex < template.Length) { // Position of the first character of the next fragment. int nextFragmentBeginningIndex; // Search for the beginning-of-special-sequence indicator. int sequenceBeginningIndex = template.IndexOf(beginOfSequenceMarker, fragmentBeginningIndex); if (sequenceBeginningIndex != -1) { // Special sequence indicator has been found. // Append to the buffer the text preceding the marker. ret.Add(new FixedToken(template.Substring(fragmentBeginningIndex, sequenceBeginningIndex - fragmentBeginningIndex))); // Ensure that the special character is not the last one in the template. if (sequenceBeginningIndex + 1 < template.Length) { // Check if the next character in the template is again the sequence marker. char nextTemplateChar = template[sequenceBeginningIndex + 1]; if (nextTemplateChar != beginOfSequenceMarker) { // Find the end-of-sequence marker. int sequenceEndingIndex = template.IndexOf(endOfSequenceMarker, sequenceBeginningIndex); if (sequenceEndingIndex != -1) { // Obtain the placeholder. string placeholder = template.Substring(sequenceBeginningIndex + 1, sequenceEndingIndex - sequenceBeginningIndex - 1); ProcessPlaceholder(placeholder, ret, wovenMethod, includeParamName); // Next fragment starts right after the sequence. nextFragmentBeginningIndex = sequenceEndingIndex + 1; } else { // Sequence is not closed. throw new FormatException(string.Format(CultureInfo.CurrentCulture, "Unfinished placeholder in template: {0}.", template)); } } else { // Repeated begin-of-sequence marker, indicates the marker should be used literally. ret.Add(new FixedToken(beginOfSequenceMarker.ToString(CultureInfo.InvariantCulture))); nextFragmentBeginningIndex = sequenceBeginningIndex + 2; } } else { // Begin-of-sequence marker is the last char in the template. throw new FormatException(string.Format(CultureInfo.CurrentCulture, "Invalid placeholder in template: {0}.", template)); } } else { // No special sequence indicator has been found. // Copy the remaining part of the template as literal message text. ret.Add(new FixedToken(template.Substring(fragmentBeginningIndex, template.Length - fragmentBeginningIndex))); // Set the index to the position which causes the parsing loop to exit. nextFragmentBeginningIndex = template.Length; } fragmentBeginningIndex = nextFragmentBeginningIndex; } return ret; }
public override void CompileTimeValidate(MethodDefDeclaration method, IMessageSink messages) { base.CompileTimeValidate(method, messages); ParameterDeclaration firstParameter = null; ParameterDeclaration secondParameter = null; foreach(var parameter in method.Parameters) { if(parameter.Name == firstParameterName) { firstParameter = parameter; } if(parameter.Name == secondParameterName) { secondParameter = parameter; } } if(firstParameter == null) { messages.Write(new Message( SeverityType.Error, "TwoParametersValidatorAttribute_ParameterNotFound", string.Format(CultureInfo.InvariantCulture, "The parameter '{0}' does not exist in method '{1}'.", firstParameterName, method.Name), GetType().FullName )); } if(secondParameter == null) { messages.Write(new Message( SeverityType.Error, "TwoParametersValidatorAttribute_ParameterNotFound", string.Format(CultureInfo.InvariantCulture, "The parameter '{0}' does not exist in method '{1}'.", secondParameterName, method.Name), GetType().FullName )); } if(firstParameter != null && secondParameter != null) { if(firstParameterName == secondParameterName) { { messages.Write(new Message( SeverityType.Error, "TwoParametersValidatorAttribute_CantSpecifyTheSameParameter", "The same name has been specified for both parameters.", GetType().FullName )); } } else { CompileTimeValidateParameters(method, messages, firstParameter, secondParameter); } } }
public CollectParametersAdvice(MethodDefDeclaration declaration) { this.declaration = declaration; }
public override void Implement(TransformationContext context) { TypeDefDeclaration typeDef = (TypeDefDeclaration)context.TargetElement; ModuleDeclaration module = this.AspectWeaver.Module; ITypeSignature baseEntityType = module.Cache.GetType(typeof(BaseEntity)); // Find the base method. IMethod baseCopyToMethod = null; IType baseTypeCursor = typeDef; MethodSignature methodSignature = new MethodSignature(module, CallingConvention.HasThis, module.Cache.GetIntrinsic(IntrinsicType.Void), new[] { baseEntityType }, 0); while (baseCopyToMethod == null && baseTypeCursor != null) { TypeDefDeclaration baseTypeCursorTypeDef = baseTypeCursor.GetTypeDefinition(); baseCopyToMethod = baseTypeCursorTypeDef.Methods.GetMethod("CopyTo", methodSignature.Translate(baseTypeCursorTypeDef.Module), BindingOptions.OnlyExisting | BindingOptions.DontThrowException); baseTypeCursor = baseTypeCursorTypeDef.BaseType; } if (baseCopyToMethod == null) { throw new AssertionFailedException("Could not find a method CopyTo."); } if (baseCopyToMethod.DeclaringType == typeDef) { return; } // Declare the method. MethodDefDeclaration methodDef = new MethodDefDeclaration { Name = "CopyTo", Attributes = (MethodAttributes.Family | MethodAttributes.ReuseSlot | MethodAttributes.Virtual), CallingConvention = CallingConvention.HasThis }; typeDef.Methods.Add(methodDef); methodDef.CustomAttributes.Add(this.AspectWeaver.AspectInfrastructureTask.WeavingHelper.GetDebuggerNonUserCodeAttribute()); // Define parameter. methodDef.ReturnParameter = new ParameterDeclaration { ParameterType = module.Cache.GetIntrinsic(IntrinsicType.Void), Attributes = ParameterAttributes.Retval }; ParameterDeclaration cloneParameter = new ParameterDeclaration(0, "clone", baseEntityType); methodDef.Parameters.Add(cloneParameter); // Define the body MethodBodyDeclaration methodBody = new MethodBodyDeclaration(); methodDef.MethodBody = methodBody; InstructionBlock instructionBlock = methodBody.CreateInstructionBlock(); methodBody.RootInstructionBlock = instructionBlock; InstructionSequence sequence = methodBody.CreateInstructionSequence(); instructionBlock.AddInstructionSequence(sequence, NodePosition.After, null); using (InstructionWriter writer = new InstructionWriter()) { writer.AttachInstructionSequence(sequence); // Cast the argument and store it in a local variable. IType typeSpec = GenericHelper.GetTypeCanonicalGenericInstance(typeDef); LocalVariableSymbol castedCloneLocal = instructionBlock.DefineLocalVariable(typeSpec, "typedClone"); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionType(OpCodeNumber.Castclass, typeSpec); writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, castedCloneLocal); // TODO: support generic base types. // Call the base method. writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstruction(OpCodeNumber.Ldarg_1); writer.EmitInstructionMethod(OpCodeNumber.Call, (IMethod)baseCopyToMethod.Translate(typeDef.Module)); // Loop on all fields and clone cloneable ones. TypeRefDeclaration cloneableTypeRef = (TypeRefDeclaration) module.Cache.GetType(typeof(ICloneable)); MethodRefDeclaration cloneMethodRef = (MethodRefDeclaration)cloneableTypeRef.MethodRefs.GetMethod( "Clone", new MethodSignature( module, CallingConvention.HasThis, module.Cache.GetIntrinsic( IntrinsicType.Object), new ITypeSignature[0], 0), BindingOptions.Default); foreach (FieldDefDeclaration fieldDef in typeDef.Fields) { if ((fieldDef.Attributes & FieldAttributes.Static) != 0) { continue; } if (fieldDef.FieldType == module.Cache.GetIntrinsic(IntrinsicType.String)) { continue; } // Does not work? //bool cloneable = fieldDef.FieldType.Inherits(cloneableTypeRef, GenericMap.Empty); bool cloneable = typeof(ICloneable).IsAssignableFrom(fieldDef.FieldType.GetSystemType(null, null)); if (cloneable) { IField fieldSpec = GenericHelper.GetFieldCanonicalGenericInstance(fieldDef); bool isValueType = fieldSpec.FieldType.BelongsToClassification(TypeClassifications.ValueType).Equals( NullableBool.True); InstructionSequence nextSequence = null; if (!isValueType) { nextSequence = methodBody.CreateInstructionSequence(); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse, nextSequence); } writer.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, castedCloneLocal); writer.EmitInstruction(OpCodeNumber.Ldarg_0); writer.EmitInstructionField(OpCodeNumber.Ldfld, fieldSpec); if (isValueType) { writer.EmitInstructionType(OpCodeNumber.Box, fieldSpec.FieldType); } //writer.EmitInstructionType(OpCodeNumber.Castclass, cloneableTypeRef); writer.EmitInstructionMethod(OpCodeNumber.Callvirt, cloneMethodRef); if (isValueType) { writer.EmitInstructionType(OpCodeNumber.Unbox, fieldSpec.FieldType); writer.EmitInstructionType(OpCodeNumber.Ldobj, fieldSpec.FieldType); } else { writer.EmitInstructionType(OpCodeNumber.Castclass, fieldSpec.FieldType); } writer.EmitInstructionField(OpCodeNumber.Stfld, fieldSpec); if (!isValueType) { writer.DetachInstructionSequence(); instructionBlock.AddInstructionSequence(nextSequence, NodePosition.After, sequence); sequence = nextSequence; writer.AttachInstructionSequence(sequence); } } } writer.EmitInstruction(OpCodeNumber.Ret); writer.DetachInstructionSequence(); } }
private MethodDefDeclaration CreateTraceStringFormatWrapper( string name ) { MethodDefDeclaration formatWrapperMethod = new MethodDefDeclaration { Name = name, Attributes = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, }; this.implementationType.Methods.Add( formatWrapperMethod ); formatWrapperMethod.Parameters.Add( new ParameterDeclaration( 0, "format", this.module.Cache.GetIntrinsic( IntrinsicType.String ) ) ); formatWrapperMethod.Parameters.Add( new ParameterDeclaration( 1, "args", this.module.Cache.GetType( typeof(object[]) ) ) ); InstructionBlock block = formatWrapperMethod.MethodBody.CreateInstructionBlock(); formatWrapperMethod.MethodBody.RootInstructionBlock = block; InstructionSequence sequence = block.AddInstructionSequence( null, NodePosition.After, null ); this.writer.AttachInstructionSequence( sequence ); for ( int i = 0; i < formatWrapperMethod.Parameters.Count; i++ ) { this.writer.EmitInstructionInt16( OpCodeNumber.Ldarg, (short) i ); } this.writer.EmitInstructionMethod( OpCodeNumber.Call, this.stringFormatArrayMethod ); this.EmitCallHandler( this.traceWriteLineMethod ); this.writer.EmitInstruction( OpCodeNumber.Ret ); this.writer.DetachInstructionSequence(); return formatWrapperMethod; }
public void Weave(WeavingContext context, PostSharp.CodeModel.InstructionBlock block) { TypeDefDeclaration typeDef = m_type; // Declare the static field FieldDefDeclaration fieldDef = new FieldDefDeclaration(); fieldDef.Attributes = FieldAttributes.Private | FieldAttributes.Static | FieldAttributes.NotSerialized | FieldAttributes.InitOnly; fieldDef.Name = "s_instance"; fieldDef.FieldType = typeDef; typeDef.Fields.Add(fieldDef); // Declare the static accessor. PropertyDeclaration propDef = new PropertyDeclaration(); propDef.Name = "Instance"; typeDef.Properties.Add(propDef); MethodSemanticDeclaration sematic = new MethodSemanticDeclaration(); sematic.Semantic = MethodSemantics.Getter; MethodDefDeclaration methodDef = new MethodDefDeclaration(); methodDef.Name = "get_Instance"; methodDef.Attributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.SpecialName; methodDef.CallingConvention = CallingConvention.Default; typeDef.Methods.Add(methodDef); ParameterDeclaration retVal = new ParameterDeclaration(); retVal.ParameterType = typeDef; retVal.Attributes = ParameterAttributes.Retval; methodDef.ReturnParameter = retVal; sematic.Method = methodDef; propDef.Members.Add(sematic); propDef.PropertyType = typeDef; methodDef.MethodBody = new MethodBodyDeclaration(); methodDef.MethodBody.MaxStack = 1; methodDef.MethodBody.RootInstructionBlock = methodDef.MethodBody.CreateInstructionBlock(); //throw new NotFiniteNumberException(); InstructionSequence sequence = methodDef.MethodBody.CreateInstructionSequence(); methodDef.MethodBody.RootInstructionBlock.AddInstructionSequence(sequence, NodePosition.After , null); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionField(OpCodeNumber.Ldsfld, typeDef.Fields.GetByName("s_instance")); context.InstructionWriter.EmitInstruction(OpCodeNumber.Ret); context.InstructionWriter.DetachInstructionSequence(); // code for the static constructor sequence = context.Method.MethodBody.CreateInstructionSequence(); block.AddInstructionSequence(sequence, NodePosition.Before, null); context.InstructionWriter.AttachInstructionSequence(sequence); context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj, typeDef.Methods.GetOneByName(".ctor")); context.InstructionWriter.EmitInstructionField(OpCodeNumber.Stsfld, typeDef.Fields.GetByName("s_instance")); context.InstructionWriter.DetachInstructionSequence(); // Change visibility to the constructor typeDef.Methods.GetOneByName(".ctor").Attributes = MethodAttributes.Private | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName; }
private MethodDefDeclaration CreateWrapperMethod( IMethod loggerMethod ) { MethodDefDeclaration wrapperMethod = new MethodDefDeclaration { Name = this.implementationType.Methods.GetUniqueName( loggerMethod.Name + "{0}" ), Attributes = MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.HideBySig, }; this.implementationType.Methods.Add( wrapperMethod ); wrapperMethod.ReturnParameter = new ParameterDeclaration { Attributes = ParameterAttributes.Retval, ParameterType = this.module.Cache.GetIntrinsic( IntrinsicType.Void ) }; ITypeSignature loggerFieldType = loggerMethod.DeclaringType.GetNakedType(); MethodDefDeclaration loggerMethodDefinition = loggerMethod.GetMethodDefinition(); if ( !loggerMethodDefinition.IsStatic ) { wrapperMethod.Parameters.Add( new ParameterDeclaration( 0, "logger", loggerFieldType ) ); } for ( int i = 0; i < loggerMethodDefinition.Parameters.Count; i++ ) { ParameterDeclaration parameter = loggerMethodDefinition.Parameters[i]; wrapperMethod.Parameters.Add( new ParameterDeclaration( wrapperMethod.Parameters.Count, parameter.Name, parameter.ParameterType.TranslateType( this.module ) ) ); } this.EmitWrapperCallBody( wrapperMethod, loggerMethod ); return wrapperMethod; }
private void EmitMessage(InstructionBlock block, InstructionWriter writer, LogLevel logLevel, string messageFormatString, int[] arguments, ITypeSignature exceptionType = null) { MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration; if (targetMethod == null) { return; } // TODO: nested types string category = targetMethod.DeclaringType.Name; ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category); InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null); writer.AttachInstructionSequence(sequence); LocalVariableSymbol exceptionLocal = null; if (exceptionType != null) { exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable( exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex")); } if (builder.SupportsIsEnabled) { builder.EmitGetIsEnabled(writer, logLevel); InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence); writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence); } bool useWrapper = ShouldUseWrapper(targetMethod); Action <InstructionWriter> getExceptionAction = exceptionLocal != null ? (Action <InstructionWriter>)(w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal)) : null; builder.EmitWrite(writer, messageFormatString, exceptionType == null ? arguments.Length : arguments.Length + 1, logLevel, getExceptionAction, (i, instructionWriter) => { if (i < arguments.Length) { int index = arguments[i]; if (index == MessageArgumentsFormatter.ThisArgumentPosition) { this.methodMappingWriter.EmitLoadInstance(false, instructionWriter); } else if (index == MessageArgumentsFormatter.ReturnParameterPosition) { instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, Context.ReturnValueVariable); instructionWriter.EmitConvertToObject( Context.MethodMapping.MethodSignature.ReturnType); } else { this.methodMappingWriter.EmitLoadArgument(index, instructionWriter); instructionWriter.EmitConvertToObject(this.methodMappingWriter.MethodMapping.MethodSignature.GetParameterType(index).GetNakedType(TypeNakingOptions.IgnoreManagedPointers)); } } else { //Emit exception parameter instructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal); } }, useWrapper); if (exceptionType == null) { writer.DetachInstructionSequence(); } }
private void EmitContstructorBlock( MethodDefDeclaration staticConstructor ) { this.constructorBlock = staticConstructor.MethodBody.RootInstructionBlock = staticConstructor.MethodBody.CreateInstructionBlock(); this.returnSequence = staticConstructor.MethodBody.RootInstructionBlock.AddInstructionSequence( null, NodePosition.After, null ); this.writer.AttachInstructionSequence( this.returnSequence ); this.writer.EmitInstruction( OpCodeNumber.Ret ); this.writer.DetachInstructionSequence(); }
private void EmitWrapperCallBody( MethodDefDeclaration wrapperMethod, IMethod loggerMethod ) { InstructionBlock rootBlock = wrapperMethod.MethodBody.CreateInstructionBlock(); wrapperMethod.MethodBody.RootInstructionBlock = rootBlock; InstructionBlock parentBlock = rootBlock.AddChildBlock( null, NodePosition.After, null ); InstructionBlock tryBlock = rootBlock.AddChildBlock( null, NodePosition.After, null ); InstructionBlock leaveTryBlock = rootBlock.AddChildBlock( null, NodePosition.After, null ); InstructionSequence sequence = parentBlock.AddInstructionSequence( null, NodePosition.After, null ); // set isLogging to true this.writer.AttachInstructionSequence( sequence ); this.writer.EmitInstruction( OpCodeNumber.Ldc_I4_1 ); this.writer.EmitInstructionField( OpCodeNumber.Stsfld, this.isLoggingField ); this.writer.DetachInstructionSequence(); // if isLogging is true, return InstructionSequence branchSequence = parentBlock.AddInstructionSequence( null, NodePosition.Before, null ); this.writer.AttachInstructionSequence( branchSequence ); this.writer.EmitInstructionField( OpCodeNumber.Ldsfld, this.isLoggingField ); this.writer.EmitBranchingInstruction( OpCodeNumber.Brfalse_S, sequence ); this.writer.EmitInstruction( OpCodeNumber.Ret ); this.writer.DetachInstructionSequence(); // return instruction at the end of the method InstructionSequence retSequence = leaveTryBlock.AddInstructionSequence( null, NodePosition.After, null ); this.writer.AttachInstructionSequence( retSequence ); this.writer.EmitInstruction( OpCodeNumber.Ret ); this.writer.DetachInstructionSequence(); InstructionSequence trySequence = tryBlock.AddInstructionSequence( null, NodePosition.After, null ); this.writer.AttachInstructionSequence( trySequence ); for ( int i = 0; i < wrapperMethod.Parameters.Count; i++ ) { writer.EmitInstructionInt16( OpCodeNumber.Ldarg, (short) i ); } this.EmitCallHandler( loggerMethod ); this.writer.DetachInstructionSequence(); InstructionSequence leaveSequence = tryBlock.AddInstructionSequence( null, NodePosition.After, null ); this.writer.AttachInstructionSequence( leaveSequence ); this.writer.EmitBranchingInstruction( OpCodeNumber.Leave, retSequence ); this.writer.DetachInstructionSequence(); InstructionBlock protectedBlock; InstructionBlock[] catchBlocks; InstructionBlock finallyBlock; this.weavingHelper.AddExceptionHandlers( this.writer, tryBlock, leaveSequence, null, true, out protectedBlock, out catchBlocks, out finallyBlock ); InstructionSequence finallySequence = finallyBlock.AddInstructionSequence( null, NodePosition.After, null ); this.writer.AttachInstructionSequence( finallySequence ); this.writer.EmitInstruction( OpCodeNumber.Ldc_I4_0 ); this.writer.EmitInstructionField( OpCodeNumber.Stsfld, this.isLoggingField ); //this.writer.EmitInstruction(OpCodeNumber.Endfinally); this.writer.DetachInstructionSequence(); }
/// <summary> /// Creates token for the specified placeholder. /// </summary> /// <param name="placeholder">Placeholder to create token for.</param> /// <param name="target">List to appent the token to.</param> /// <param name="wovenMethod">Method being woven.</param> /// <param name="includeParamName">Indicates, whether parameter names should be included in the log.</param> /// <exception cref="ArgumentNullException"><paramref name="placeholder"/>, <paramref name="target"/> or <paramref name="wovenMethod"/> is <see langword="null"/>.</exception> /// <exception cref="FormatException"><paramref name="placeholder"/> is invalid or unrecognized placeholder.</exception> private static void ProcessPlaceholder(string placeholder, ICollection<IMessageToken> target, MethodDefDeclaration wovenMethod, bool includeParamName) { if (placeholder == null) { throw new ArgumentNullException("placeholder"); } if (target == null) { throw new ArgumentNullException("target"); } if (wovenMethod == null) { throw new ArgumentNullException("wovenMethod"); } if (string.Equals(placeholder, signaturePlaceholder, StringComparison.InvariantCulture)) { target.Add(new FixedToken(GetMethodSignature(wovenMethod))); } else if (string.Equals(placeholder, methodNamePlaceholder, StringComparison.InvariantCulture)) { target.Add(new FixedToken(wovenMethod.Name)); } else if (placeholder.StartsWith(parameterPrefix, StringComparison.InvariantCulture)) { // Extract the name of the parameter. string parameterName = placeholder.Substring(parameterPrefix.Length); ParameterDeclaration referredParameter = null; foreach (ParameterDeclaration parameter in wovenMethod.Parameters) { if (string.Equals(parameter.Name, parameterName, StringComparison.InvariantCulture)) { referredParameter = parameter; break; } } if (referredParameter == null) { throw new FormatException(string.Format(CultureInfo.CurrentCulture, "Invalid parameter name: {0}.", parameterName)); } target.Add(new ParameterValueToken(referredParameter)); } else if (string.Equals(placeholder, shortParameterList, StringComparison.InvariantCulture)) { AddParamsMessageTokens(target, wovenMethod.Parameters, includeParamName); } else if (string.Equals(placeholder, shortInParameterList, StringComparison.InvariantCulture)) { AddParamsMessageTokens(target, YieldInParameters(wovenMethod), includeParamName); } else if (string.Equals(placeholder, shortOutParameterList, StringComparison.InvariantCulture)) { AddParamsMessageTokens(target, YieldOutParameters(wovenMethod), includeParamName); } else if (string.Equals(placeholder, returnValue, StringComparison.InvariantCulture)) { target.Add(new ReturnValueToken(wovenMethod.ReturnParameter)); } else { throw new FormatException(string.Format(CultureInfo.CurrentCulture, "Unknown placeholder in template: {0}.", placeholder)); } }
public MethodDefDeclaration GetTraceStringFormatMethod() { return this.traceWriteLineWrapperMethod ?? (this.traceWriteLineWrapperMethod = this.CreateTraceStringFormatWrapper( "TraceWriteLineFormat" )); }
/// <summary> /// Yields all the output parameters of the given woven method. /// </summary> /// <param name="wovenMethod">A woven method.</param> private static IEnumerable<ParameterDeclaration> YieldOutParameters(MethodDefDeclaration wovenMethod) { foreach (ParameterDeclaration parameter in wovenMethod.Parameters) { if ((parameter.Attributes & (ParameterAttributes.Out | ParameterAttributes.Retval)) != 0 || parameter.ParameterType.BelongsToClassification(TypeClassifications.Pointer)) { yield return parameter; } } }
private static void CustomMethodSignatureError(TypeDefDeclaration enhancedType, MethodDefDeclaration method) { string message = $"Method {method.Name} marked with [CustomEqualsInternal] must be public, instance, must return bool and accept 1 parameter of the same type as the declaring type {enhancedType.Name}"; throw new InjectionException("EQU3", message); }