Example #1
0
        /// <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);
        }
Example #2
0
        /// <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);
        }