<commit_before>﻿using Mono.Cecil;
using Mono.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace DocfxAnnotationGenerator
{
    /// <summary>
    /// A member loaded via reflection.
    /// </summary>
    public class ReflectionMember
    {
        /// <summary>
        /// The UID Docfx would use for this member. See
        /// https://dotnet.github.io/docfx/spec/metadata_dotnet_spec.html
        /// </summary>
        public string DocfxUid { get; }

        // Never null, but only actually relevant for methods, properties and indexers.
        public IEnumerable<string> NotNullParameters { get; } = Enumerable.Empty<string>();

        // Methods, indexers, properties.
        public bool NotNullReturn { get; }

        public static IEnumerable<ReflectionMember> Load(Stream stream) =>
            ModuleDefinition.ReadModule(stream).Types.Where(t => t.IsPublic).SelectMany(GetMembers);

        private static IEnumerable<ReflectionMember> GetMembers(TypeDefinition type)
        {
            yield return new ReflectionMember(type);

            if (type.BaseType?.FullName == "System.MulticastDelegate")
            {
                yield break;
            }

            foreach (var property in type.Properties.Where(p => IsAccessible(p.GetMethod) || IsAccessible(p.SetMethod)))
            {
                yield return new ReflectionMember(property);
            }

            // TODO: Do we want protected methods?
            foreach (var method in type.Methods.Where(m => !m.IsGetter && !m.IsSetter && IsAccessible(m)))
            {
                yield return new ReflectionMember(method);
            }

            foreach (var field in type.Fields.Where(m => m.IsPublic && !m.IsSpecialName))
            {
                yield return new ReflectionMember(field);
            }

            foreach (var nestedMember in type.NestedTypes.Where(t => t.IsNestedPublic).SelectMany(GetMembers))
            {
                yield return nestedMember;
            }
        }

        private static bool IsAccessible(MethodDefinition method)
        {
            // This is pretty crude at the moment...
            // Handy for properties
            if (method == null)
            {
                return false;
            }
            // Overrides is used to check for explicit interface implementation
            return method.IsPublic || method.IsFamily || method.Overrides.Count != 0;
        }

        // TODO: More specifically, is it an explicit interface implementation for a public interface?
        // (Doesn't seem to affect us right now...)

        private ReflectionMember(TypeDefinition type)
        {
            DocfxUid = GetUid(type);
        }

        private ReflectionMember(PropertyDefinition property)
        {
            // property.Name will be Type.Name for explicit interface implementations, e.g. NodaTime.IClock.Now
            DocfxUid = $"{GetUid(property.DeclaringType)}.{property.Name.Replace('.', '#')}{GetParameterNames(property.Parameters)}";
            NotNullReturn = HasNotNullAttribute(property);
        }

        private ReflectionMember(MethodDefinition method)
        {
            DocfxUid = GetUid(method);
            NotNullReturn = HasNotNullAttribute(method);
            NotNullParameters = method.Parameters.Where(p => HasNotNullAttribute(p)).Select(p => p.Name).ToList();
        }
<commit_msg>Don't add exception docs for NotNull out parameters<commit_after>﻿using Mono.Cecil;
using Mono.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace DocfxAnnotationGenerator
{
    /// <summary>
    /// A member loaded via reflection.
    /// </summary>
    public class ReflectionMember
    {
        /// <summary>
        /// The UID Docfx would use for this member. See
        /// https://dotnet.github.io/docfx/spec/metadata_dotnet_spec.html
        /// </summary>
        public string DocfxUid { get; }

        // Never null, but only actually relevant for methods, properties and indexers.
        public IEnumerable<string> NotNullParameters { get; } = Enumerable.Empty<string>();

        // Methods, indexers, properties.
        public bool NotNullReturn { get; }

        public static IEnumerable<ReflectionMember> Load(Stream stream) =>
            ModuleDefinition.ReadModule(stream).Types.Where(t => t.IsPublic).SelectMany(GetMembers);

        private static IEnumerable<ReflectionMember> GetMembers(TypeDefinition type)
        {
            yield return new ReflectionMember(type);

            if (type.BaseType?.FullName == "System.MulticastDelegate")
            {
                yield break;
            }

            foreach (var property in type.Properties.Where(p => IsAccessible(p.GetMethod) || IsAccessible(p.SetMethod)))
            {
                yield return new ReflectionMember(property);
            }

            // TODO: Do we want protected methods?
            foreach (var method in type.Methods.Where(m => !m.IsGetter && !m.IsSetter && IsAccessible(m)))
            {
                yield return new ReflectionMember(method);
            }

            foreach (var field in type.Fields.Where(m => m.IsPublic && !m.IsSpecialName))
            {
                yield return new ReflectionMember(field);
            }

            foreach (var nestedMember in type.NestedTypes.Where(t => t.IsNestedPublic).SelectMany(GetMembers))
            {
                yield return nestedMember;
            }
        }

        private static bool IsAccessible(MethodDefinition method)
        {
            // This is pretty crude at the moment...
            // Handy for properties
            if (method == null)
            {
                return false;
            }
            // Overrides is used to check for explicit interface implementation
            return method.IsPublic || method.IsFamily || method.Overrides.Count != 0;
        }

        // TODO: More specifically, is it an explicit interface implementation for a public interface?
        // (Doesn't seem to affect us right now...)

        private ReflectionMember(TypeDefinition type)
        {
            DocfxUid = GetUid(type);
        }

        private ReflectionMember(PropertyDefinition property)
        {
            // property.Name will be Type.Name for explicit interface implementations, e.g. NodaTime.IClock.Now
            DocfxUid = $"{GetUid(property.DeclaringType)}.{property.Name.Replace('.', '#')}{GetParameterNames(property.Parameters)}";
            NotNullReturn = HasNotNullAttribute(property);
        }

        private ReflectionMember(MethodDefinition method)
        {
            DocfxUid = GetUid(method);
            NotNullReturn = HasNotNullAttribute(method);
            NotNullParameters = method.Parameters.Where(p => HasNotNullAttribute(p) && !p.IsOut).Select(p => p.Name).ToList();
        }

{'fraction_non_alphanumeric': 0.09840501281686129, 'fraction_numerical': 0.0002848191398461977, 'mean_word_length': 2.0735229759299783, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 35, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3743042', 'n_tokens_mistral': 1781, 'n_tokens_neox': 1728, 'n_words': 454}