File: Linker.Steps\ReflectionBlockedStep.cs
Web Access
Project: src\src\tools\illink\src\linker\Mono.Linker.csproj (illink)
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
 
using System;
using System.Diagnostics;
using Mono.Cecil;
 
namespace Mono.Linker.Steps
{
    public class ReflectionBlockedStep : BaseStep
    {
        AssemblyDefinition? assembly;
        AssemblyDefinition Assembly
        {
            get
            {
                Debug.Assert(assembly != null);
                return assembly;
            }
        }
 
        protected override void ProcessAssembly(AssemblyDefinition assembly)
        {
            this.assembly = assembly;
 
            foreach (var type in assembly.MainModule.Types)
                ProcessType(type);
        }
 
        void ProcessType(TypeDefinition type)
        {
            if (!HasIndirectCallers(type))
            {
                AddCustomAttribute(type);
                return;
            }
 
            //
            // We mark everything, otherwise we would need to check full visibility
            // hierarchy (e.g. public method inside private type)
            //
            foreach (var method in type.Methods)
            {
                if (!Annotations.IsIndirectlyCalled(method))
                {
                    AddCustomAttribute(method);
                }
            }
 
            foreach (var nested in type.NestedTypes)
                ProcessType(nested);
        }
 
        bool HasIndirectCallers(TypeDefinition type)
        {
            foreach (var method in type.Methods)
            {
                if (Annotations.IsIndirectlyCalled(method))
                    return true;
            }
 
            if (type.HasNestedTypes)
            {
                foreach (var nested in type.NestedTypes)
                {
                    if (HasIndirectCallers(nested))
                        return true;
                }
            }
 
            return false;
        }
 
        void AddCustomAttribute(ICustomAttributeProvider caProvider)
        {
            // We are using DisableReflectionAttribute which is not exact match but it's quite
            // close to what we need and it already exists in the BCL
            MethodReference ctor = Context.MarkedKnownMembers.DisablePrivateReflectionAttributeCtor ?? throw new InvalidOperationException();
            ctor = Assembly.MainModule.ImportReference(ctor);
 
            var ca = new CustomAttribute(ctor);
            caProvider.CustomAttributes.Add(ca);
            Annotations.Mark(ca, new DependencyInfo(DependencyKind.DisablePrivateReflection, ca));
        }
    }
}