|
// 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);
}
}
}
}
|