protected internal override void OnPopulate(TreeViewCancelEventArgs e)
        {
            TypeRefDeclaration externalType = this.Declaration as TypeRefDeclaration;

            if (externalType.TypeRefs.Count > 0)
            {
                this.Nodes.Add(new ExternalTypeFolderTreeNode(externalType, "Nested Types"));
            }

            ExternalFieldTreeNode.PopulateExternalMembers(externalType, this.Nodes, false);
        }
 public ExternalTypeTreeNode( TypeRefDeclaration externalType )
     : base( externalType, TreeViewImage.Class, TreeViewImage.Reference )
 {
     this.Text = externalType.Name;
     this.EnableLatePopulate();
 }
            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();
                }
            }
 public ExternalTypeTreeNode(TypeRefDeclaration externalType)
     : base(externalType, TreeViewImage.Class, TreeViewImage.Reference)
 {
     this.Text = externalType.Name;
     this.EnableLatePopulate();
 }