Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ internal static string GetGenericParameterDeclaringMemberDisplayName(GenericPara
return ((TypeDesc)parent).GetDisplayName();
}

internal static string GetRequiresUnreferencedCodeAttributeMessage(MethodDesc method)
internal static string GetRequiresAttributeMessage(MethodDesc method, string requiresAttributeName)
{
var ecmaMethod = method.GetTypicalMethodDefinition() as EcmaMethod;
if (ecmaMethod == null)
return null;

var decoded = ecmaMethod.GetDecodedCustomAttribute("System.Diagnostics.CodeAnalysis", "RequiresUnreferencedCodeAttribute");
var decoded = ecmaMethod.GetDecodedCustomAttribute("System.Diagnostics.CodeAnalysis", requiresAttributeName);
if (decoded == null)
return null;

Expand All @@ -62,20 +62,20 @@ internal static string GetRequiresUnreferencedCodeAttributeMessage(MethodDesc me
return null;
}

internal static string GetRequiresDynamicCodeAttributeMessage(MethodDesc method)
internal static string GetRequiresAttributeUrl(MethodDesc method, string requiresAttributeName)
{
var ecmaMethod = method.GetTypicalMethodDefinition() as EcmaMethod;
if (ecmaMethod == null)
return null;

var decoded = ecmaMethod.GetDecodedCustomAttribute("System.Diagnostics.CodeAnalysis", "RequiresDynamicCodeAttribute");
var decoded = ecmaMethod.GetDecodedCustomAttribute("System.Diagnostics.CodeAnalysis", requiresAttributeName);
if (decoded == null)
return null;

var decodedValue = decoded.Value;

if (decodedValue.FixedArguments.Length != 0)
return (string)decodedValue.FixedArguments[0].Value;
if (decodedValue.NamedArguments.Length != 0 && decodedValue.NamedArguments[0].Name == "Url")
return (string)decodedValue.NamedArguments[0].Value;

return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using Mono.Cecil;

namespace Mono.Linker.Dataflow
{
static class DiagnosticUtilities
{
internal static IMetadataTokenProvider GetMethodParameterFromIndex (MethodDefinition method, int parameterIndex)
{
int declaredParameterIndex;
if (method.HasImplicitThis ()) {
if (parameterIndex == 0)
return method;

declaredParameterIndex = parameterIndex - 1;
} else
declaredParameterIndex = parameterIndex;

if (declaredParameterIndex >= 0 && declaredParameterIndex < method.Parameters.Count)
return method.Parameters[declaredParameterIndex];

throw new InvalidOperationException ();
}

internal static string GetParameterNameForErrorMessage (ParameterDefinition parameterDefinition) =>
string.IsNullOrEmpty (parameterDefinition.Name) ? $"#{parameterDefinition.Index}" : parameterDefinition.Name;

internal static string GetGenericParameterDeclaringMemberDisplayName (GenericParameter genericParameter) =>
genericParameter.DeclaringMethod != null ?
genericParameter.DeclaringMethod.GetDisplayName () :
genericParameter.DeclaringType.GetDisplayName ();

internal static string GetMethodSignatureDisplayName (IMethodSignature methodSignature) =>
(methodSignature is MethodReference method) ? method.GetDisplayName () : (methodSignature.ToString () ?? string.Empty);
}
}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Mono.Cecil;

#nullable enable

namespace Mono.Linker
{
// Temporary workaround - should be removed once linker can be upgraded to build against
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
Expand All @@ -9,8 +8,6 @@
using Mono.Cecil;
using Mono.Cecil.Cil;

#nullable enable

namespace Mono.Linker.Dataflow
{
class FlowAnnotations
Expand Down Expand Up @@ -589,15 +586,15 @@ readonly struct TypeAnnotations
{
readonly TypeDefinition _type;
readonly DynamicallyAccessedMemberTypes _typeAnnotation;
readonly MethodAnnotations[] _annotatedMethods;
readonly FieldAnnotation[] _annotatedFields;
readonly MethodAnnotations[]? _annotatedMethods;
readonly FieldAnnotation[]? _annotatedFields;
readonly DynamicallyAccessedMemberTypes[]? _genericParameterAnnotations;

public TypeAnnotations (
TypeDefinition type,
DynamicallyAccessedMemberTypes typeAnnotation,
MethodAnnotations[] annotatedMethods,
FieldAnnotation[] annotatedFields,
MethodAnnotations[]? annotatedMethods,
FieldAnnotation[]? annotatedFields,
DynamicallyAccessedMemberTypes[]? genericParameterAnnotations)
=> (_type, _typeAnnotation, _annotatedMethods, _annotatedFields, _genericParameterAnnotations)
= (type, typeAnnotation, annotatedMethods, annotatedFields, genericParameterAnnotations);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
Expand All @@ -9,8 +8,6 @@
using Mono.Cecil.Cil;
using Mono.Collections.Generic;

#nullable enable

namespace Mono.Linker.Dataflow
{
/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Sources taken from https://github.com/dotnet/linker/tree/640878adf1e27cb79bea0a894033f85a84db208d/src/linker/Linker.Dataflow.
Sources taken from https://github.com/dotnet/linker/tree/9996319f2a619c2911b02c164b4d6b1d20e29a39/src/linker/Linker.Dataflow.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
Expand All @@ -14,8 +13,6 @@

using BindingFlags = System.Reflection.BindingFlags;

#nullable enable

namespace Mono.Linker.Dataflow
{
class ReflectionMethodBodyScanner : MethodBodyScanner
Expand Down Expand Up @@ -894,8 +891,7 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c
// We have one of the accessors for the property. The Expression.Property will in this case search
// for the matching PropertyInfo and store that. So to be perfectly correct we need to mark the
// respective PropertyInfo as "accessed via reflection".
var propertyDefinition = methodBaseValue.MethodRepresented.GetProperty ();
if (propertyDefinition != null) {
if (methodBaseValue.MethodRepresented.TryGetProperty (out PropertyDefinition? propertyDefinition)) {
MarkProperty (ref reflectionContext, propertyDefinition);
continue;
}
Expand Down Expand Up @@ -1051,15 +1047,14 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c
}
foreach (var typeNameValue in methodParams[0].UniqueValues ()) {
if (typeNameValue is KnownStringValue knownStringValue) {
TypeReference foundTypeRef = _context.TypeNameResolver.ResolveTypeName (knownStringValue.Contents, callingMethodDefinition, out AssemblyDefinition typeAssembly, false);
TypeDefinition? foundType = ResolveToTypeDefinition (foundTypeRef);
if (foundType == null) {
if (!_context.TypeNameResolver.TryResolveTypeName (knownStringValue.Contents, callingMethodDefinition, out TypeReference? foundTypeRef, out AssemblyDefinition? typeAssembly, false)
|| ResolveToTypeDefinition (foundTypeRef) is not TypeDefinition foundType) {
// Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back.
reflectionContext.RecordHandledPattern ();
} else {
reflectionContext.RecordRecognizedPattern (foundType, () => _markStep.MarkTypeVisibleToReflection (foundTypeRef, foundType, new DependencyInfo (DependencyKind.AccessedViaReflection, callingMethodDefinition)));
methodReturnValue = MergePointValue.MergeValues (methodReturnValue, new SystemTypeValue (foundType));
_context.MarkingHelpers.MarkMatchingExportedType (foundType, typeAssembly, new DependencyInfo (DependencyKind.AccessedViaReflection, foundType));
_context.MarkingHelpers.MarkMatchingExportedType (foundType, typeAssembly, new DependencyInfo (DependencyKind.AccessedViaReflection, foundType), reflectionContext.Origin);
}
} else if (typeNameValue == NullValue.Instance) {
reflectionContext.RecordHandledPattern ();
Expand Down Expand Up @@ -1200,7 +1195,7 @@ public override bool HandleCall (MethodBody callingMethodBody, MethodReference c
// We have chosen not to populate the methodReturnValue for now
RequireDynamicallyAccessedMembers (ref reflectionContext, DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes, value, calledMethodDefinition);
else {
TypeDefinition[] matchingNestedTypes = MarkNestedTypesOnType (ref reflectionContext, systemTypeValue.TypeRepresented, m => m.Name == stringValue.Contents, bindingFlags);
TypeDefinition[]? matchingNestedTypes = MarkNestedTypesOnType (ref reflectionContext, systemTypeValue.TypeRepresented, m => m.Name == stringValue.Contents, bindingFlags);

if (matchingNestedTypes != null) {
for (int i = 0; i < matchingNestedTypes.Length; i++)
Expand Down Expand Up @@ -1936,9 +1931,9 @@ void ProcessCreateInstanceByName (ref ReflectionPatternContext reflectionContext
continue;
}

var typeRef = _context.TypeNameResolver.ResolveTypeName (resolvedAssembly, typeNameStringValue.Contents);
var resolvedType = _context.TryResolve (typeRef);
if (resolvedType == null || typeRef is ArrayType) {
if (!_context.TypeNameResolver.TryResolveTypeName (resolvedAssembly, typeNameStringValue.Contents, out TypeReference? typeRef)
|| _context.TryResolve (typeRef) is not TypeDefinition resolvedType
|| typeRef is ArrayType) {
// It's not wrong to have a reference to non-existing type - the code may well expect to get an exception in this case
// Note that we did find the assembly, so it's not a linker config problem, it's either intentional, or wrong versions of assemblies
// but linker can't know that. In case a user tries to create an array using System.Activator we should simply ignore it, the user
Expand Down Expand Up @@ -2232,15 +2227,14 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC
} else if (uniqueValue is SystemTypeValue systemTypeValue) {
MarkTypeForDynamicallyAccessedMembers (ref reflectionContext, systemTypeValue.TypeRepresented, requiredMemberTypes, DependencyKind.DynamicallyAccessedMember);
} else if (uniqueValue is KnownStringValue knownStringValue) {
TypeReference typeRef = _context.TypeNameResolver.ResolveTypeName (knownStringValue.Contents, reflectionContext.Source, out AssemblyDefinition typeAssembly);
TypeDefinition? foundType = ResolveToTypeDefinition (typeRef);
if (foundType == null) {
if (!_context.TypeNameResolver.TryResolveTypeName (knownStringValue.Contents, reflectionContext.Source, out TypeReference? typeRef, out AssemblyDefinition? typeAssembly)
|| ResolveToTypeDefinition (typeRef) is not TypeDefinition foundType) {
// Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back.
reflectionContext.RecordHandledPattern ();
} else {
MarkType (ref reflectionContext, typeRef);
MarkTypeForDynamicallyAccessedMembers (ref reflectionContext, foundType, requiredMemberTypes, DependencyKind.DynamicallyAccessedMember);
_context.MarkingHelpers.MarkMatchingExportedType (foundType, typeAssembly, new DependencyInfo (DependencyKind.DynamicallyAccessedMember, foundType));
_context.MarkingHelpers.MarkMatchingExportedType (foundType, typeAssembly, new DependencyInfo (DependencyKind.DynamicallyAccessedMember, foundType), reflectionContext.Origin);
}
} else if (uniqueValue == NullValue.Instance) {
// Ignore - probably unreachable path as it would fail at runtime anyway.
Expand Down Expand Up @@ -2387,7 +2381,7 @@ void MarkFieldsOnTypeHierarchy (ref ReflectionPatternContext reflectionContext,
MarkField (ref reflectionContext, field);
}

TypeDefinition[] MarkNestedTypesOnType (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func<TypeDefinition, bool> filter, BindingFlags? bindingFlags = BindingFlags.Default)
TypeDefinition[]? MarkNestedTypesOnType (ref ReflectionPatternContext reflectionContext, TypeDefinition type, Func<TypeDefinition, bool> filter, BindingFlags? bindingFlags = BindingFlags.Default)
{
var result = new ArrayBuilder<TypeDefinition> ();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Diagnostics;
Expand All @@ -26,17 +25,17 @@ struct ReflectionPatternContext : IDisposable
#endif

public MessageOrigin Origin { get; init; }
public ICustomAttributeProvider Source { get => Origin.Provider; }
public ICustomAttributeProvider? Source { get => Origin.Provider; }
public IMetadataTokenProvider MemberWithRequirements { get; init; }
public Instruction Instruction { get; init; }
public Instruction? Instruction { get; init; }
public bool ReportingEnabled { get; init; }

public ReflectionPatternContext (
LinkContext context,
bool reportingEnabled,
in MessageOrigin origin,
IMetadataTokenProvider memberWithRequirements,
Instruction instruction = null)
Instruction? instruction = null)
{
_context = context;
ReportingEnabled = reportingEnabled;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
Expand All @@ -13,8 +12,6 @@
using GenericParameter = Mono.Cecil.GenericParameter;
using TypeDefinition = Mono.Cecil.TypeDefinition;

#nullable enable

namespace Mono.Linker.Dataflow
{
public enum ValueNodeKind
Expand Down
Loading