|
// 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.Diagnostics.CodeAnalysis;
using ILLink.Shared;
using Mono.Cecil;
namespace Mono.Linker.Steps
{
public class ValidateVirtualMethodAnnotationsStep : BaseStep
{
protected override void Process()
{
var annotations = Context.Annotations;
foreach (var method in annotations.VirtualMethodsWithAnnotationsToValidate)
{
var baseOverrideInformations = annotations.GetBaseMethods(method);
if (baseOverrideInformations != null)
{
foreach (var baseOv in baseOverrideInformations)
{
annotations.FlowAnnotations.ValidateMethodAnnotationsAreSame(baseOv);
ValidateMethodRequiresUnreferencedCodeAreSame(baseOv);
}
}
var overrides = annotations.GetOverrides(method);
if (overrides != null)
{
foreach (var overrideInformation in overrides)
{
// Skip validation for cases where both base and override are in the list, we will validate the edge
// when validating the override from the list.
// This avoids validating the edge twice (it would produce the same warning twice)
if (annotations.VirtualMethodsWithAnnotationsToValidate.Contains(overrideInformation.Override))
continue;
annotations.FlowAnnotations.ValidateMethodAnnotationsAreSame(overrideInformation);
ValidateMethodRequiresUnreferencedCodeAreSame(overrideInformation);
}
}
}
}
void ValidateMethodRequiresUnreferencedCodeAreSame(OverrideInformation ov)
{
var method = ov.Override;
var baseMethod = ov.Base;
var annotations = Context.Annotations;
bool methodSatisfies = annotations.IsInRequiresUnreferencedCodeScope(method, out _);
bool baseRequires = annotations.DoesMethodRequireUnreferencedCode(baseMethod, out _);
if ((baseRequires && !methodSatisfies) || (!baseRequires && annotations.DoesMethodRequireUnreferencedCode(method, out _)))
{
string message = MessageFormat.FormatRequiresAttributeMismatch(
methodSatisfies,
baseMethod.DeclaringType.IsInterface,
nameof(RequiresUnreferencedCodeAttribute),
method.GetDisplayName(),
baseMethod.GetDisplayName());
IMemberDefinition origin = (ov.IsOverrideOfInterfaceMember && ov.InterfaceImplementor.Implementor != method.DeclaringType)
? ov.InterfaceImplementor.Implementor
: method;
Context.LogWarning(origin, DiagnosticId.RequiresUnreferencedCodeAttributeMismatch, message);
}
}
}
}
|