/// <summary> /// Creates a method from a method definition. /// </summary> /// <param name="methodDef">The method def.</param> /// <returns>A NMethod</returns> private NMethod CreateMethodFromDefinition(NNamespace @namespace, MethodDefinition methodDef) { NMethod method; // Create the associated type if (methodDef.IsConstructor) { method = NewInstance <NConstructor>(@namespace, methodDef); // Constructors must have typename instead of .ctor method.Name = method.DeclaringType.Name; } else if (methodDef.IsSpecialName && methodDef.Name.StartsWith(MethodOperatorPrefix)) { method = NewInstance <NOperator>(@namespace, methodDef); method.Name = method.Name.Substring(MethodOperatorPrefix.Length, method.Name.Length - MethodOperatorPrefix.Length); } else { method = NewInstance <NMethod>(@namespace, methodDef); } // Setup visibility method.IsVirtual = methodDef.IsVirtual; method.IsStatic = methodDef.IsStatic; method.IsFinal = methodDef.IsFinal; method.IsAbstract = methodDef.IsAbstract; method.Assembly = CurrentAssembly; if (methodDef.IsPublic) { method.Visibility = NVisibility.Public; } else if (methodDef.IsPrivate) { method.Visibility = NVisibility.Private; } else if (methodDef.IsAssembly) { method.Visibility = NVisibility.Internal; } else if (methodDef.IsFamily) { method.Visibility = NVisibility.Protected; } else if (methodDef.IsFamilyOrAssembly) { method.Visibility = NVisibility.ProtectedInternal; } if (method.IsVirtual) { // overrides method.Overrides = GetMethodReference(@namespace, MonoCecilHelper.GetBaseMethodInTypeHierarchy(methodDef)); // implements method.Implements = GetMethodReference(@namespace, MonoCecilHelper.GetBaseMethodInInterfaceHierarchy(methodDef)); // If this method doesn't have any documentation, use inherited documentation if (string.IsNullOrEmpty(method.Description)) { method.DocNode = method.Overrides != null ? method.Overrides.DocNode : method.Implements != null ? method.Implements.DocNode : method.DocNode; } } method.ReturnType = GetTypeReference(methodDef.ReturnType); method.MemberType = NMemberType.Method; foreach (var parameter in methodDef.Parameters) { AddParameter(method, parameter); } // Display name for this method var signature = new StringBuilder(); signature.Append(method.Name); BuildMethodSignatureParameters(method, signature); method.Signature = signature.ToString(); // Force update of documentation for parameters method.OnDocNodeUpdate(); return(method); }
/// <summary> /// Adds the type. /// </summary> /// <param name="namespace">The @namespace.</param> /// <param name="typeDef">The type def.</param> private void AddType(NNamespace @namespace, TypeDefinition typeDef) { // Todo add configurable filter if (!typeDef.IsPublic && !typeDef.IsNestedPublic) { return; } var typeId = DocIdHelper.GetXmlId(typeDef); var type = (NType)_registry.FindById(typeId); // If this is a new type create and register it if (type == null) { if (typeDef.IsInterface) { type = NewInstance <NInterface>(@namespace, typeDef); type.MemberType = NMemberType.Interface; } else if (typeDef.IsEnum) { type = NewInstance <NEnum>(@namespace, typeDef); type.MemberType = NMemberType.Enum; } else if (typeDef.IsValueType) { type = NewInstance <NStruct>(@namespace, typeDef); type.MemberType = NMemberType.Struct; } else if (MonoCecilHelper.IsDelegate(typeDef)) { type = NewInstance <NDelegate>(@namespace, typeDef); type.MemberType = NMemberType.Delegate; } else if (typeDef.IsClass) { type = NewInstance <NClass>(@namespace, typeDef); type.MemberType = NMemberType.Class; } else { throw new InvalidOperationException(string.Format("Unsupported type [{0}]", typeDef.FullName)); } // Fix nested type name if (typeDef.IsNestedPublic) { type.Name = type.DeclaringType.Name + "." + type.Name; type.FullName = type.FullName.Replace("/", "."); } _registry.Register(type); @namespace.AddType(type); // Add reference to all base types var baseTypeDefinition = typeDef; do { baseTypeDefinition = MonoCecilHelper.GetBaseType(baseTypeDefinition); if (baseTypeDefinition != null) { type.Bases.Add(GetTypeReference(baseTypeDefinition)); } } while (baseTypeDefinition != null); // Flattened hierarchy initialized with all base types // Derived types will be added at a later pass, when types in all asemblies // will be discovered. var reverseBases = new List <INMemberReference>(type.Bases); reverseBases.Reverse(); for (int i = 0; i < reverseBases.Count; i++) { type.FlattenedHierarchy.Add(new Tuple <int, INMemberReference>(i, reverseBases[i])); } // Add this type itself to its flattened hierarchy type.FlattenedHierarchy.Add(new Tuple <int, INMemberReference>(reverseBases.Count, type)); // Add reference to inherited interfaces foreach (var typeReference in typeDef.Interfaces) { type.Interfaces.Add(GetTypeReference(typeReference)); } if (typeDef.IsPublic) { type.Visibility = NVisibility.Public; } else if (typeDef.IsNotPublic) { type.Visibility = NVisibility.Private; } type.IsAbstract = typeDef.IsAbstract; type.IsFinal = typeDef.IsSealed; // Revert back declaration abstract sealed class are actually declared as static class if (type is NClass && type.IsAbstract && type.IsFinal) { type.IsStatic = true; type.IsAbstract = false; type.IsFinal = false; } else if (type is NEnum || type is NStruct || type is NDelegate) { // We know that enum is sealed, so don't duplicate it type.IsFinal = false; } // Reconstruct StructLayout attribute if (typeDef.IsExplicitLayout || typeDef.IsSequentialLayout) { var layout = new StringBuilder(); layout.Append("StructLayoutAttribute("); if (typeDef.IsExplicitLayout) { layout.Append("LayoutKind.Explicit"); } else if (typeDef.IsSequentialLayout) { layout.Append("LayoutKind.Sequential"); } else { layout.Append("LayoutKind.Auto"); } if (typeDef.IsUnicodeClass) { layout.Append(", CharSet = CharSet.Unicode"); } else if (typeDef.IsAnsiClass) { layout.Append(", CharSet = CharSet.Ansi"); } else if (typeDef.IsAutoClass) { layout.Append(", CharSet = CharSet.Auto"); } if (typeDef.PackingSize != 0) { layout.Append(", Pack = ").Append(typeDef.PackingSize); } if (typeDef.ClassSize != 0) { layout.Append(", Size = ").Append(typeDef.ClassSize); } layout.Append(")"); type.Attributes.Add(layout.ToString()); } // Reconstruct Serializable attribute if (typeDef.IsSerializable) { type.Attributes.Add("SerializableAttribute"); } type.SeeAlsos.Add(new NSeeAlso(@namespace)); } // Add current group type.SetApiGroup(CurrentMergeGroup, true); // Because a type in a different assemblies can have new methods/properties/fields...etc. // We need to check that there is no new members // Add methods, constructors, operators. Todo add configurable filter foreach (var method in typeDef.Methods.Where(this.IsMemberToDisplay)) { AddMethod(type, method); } // Add fields. Todo add configurable filter foreach (var field in typeDef.Fields.Where(this.IsMemberToDisplay)) { AddField(type, field); } // Add events. Todo add configurable filter foreach (var eventInfo in typeDef.Events.Where(this.IsMemberToDisplay)) { AddEvent(type, eventInfo); } // Add properties Todo add configurable filter foreach (var property in typeDef.Properties.Where(this.IsMemberToDisplay)) { AddProperty(type, property); } // For enumeration, we are only using MsdnId from enum if (type is NEnum) { foreach (var field in type.Fields) { field.MsdnId = type.MsdnId; } } // Add nested types to the global namespace. foreach (var nestedType in typeDef.NestedTypes) { AddType(@namespace, nestedType); } UpdatePageTitle(type); }