mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-08 03:27:04 +09:00
Fix type parsing issues in ILLink and ILC (#104060)
- Fixes https://github.com/dotnet/runtime/issues/98955 We will now produce a warning when a non-assembly-qualified type flows into a string location annotated with DynamicallyAccessedMembers, and we don't try to look up or mark the type (since we don't know which assemblies will be searched at runtime by the Type.GetType call). - Fixes https://github.com/dotnet/runtime/issues/103906 The ILLink intrinsic handling for `Type.GetType` will now look in corelib for generic arguments, matching native AOT. This replaces the existing warning IL2105. This uses a new warning instead of repurposing IL2105, because we already documented IL2105 and older versions of ILLink will produce it. Best to avoid any confusion about them.
This commit is contained in:
parent
856a0a6f5e
commit
9407c9cfa8
30 changed files with 308 additions and 136 deletions
|
@ -1870,6 +1870,22 @@ void TestMethod()
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### `IL2122`: Type 'typeName' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
|
||||||
|
|
||||||
|
- The type name string passed to a location with `DynamicallyAccessedMembers` requirements was not assembly-qualified, so the trimmer cannot guarantee that the type is preserved. Consider using an assembly-qualified name instead.
|
||||||
|
|
||||||
|
```C#
|
||||||
|
// warning IL2122: Type 'MyClass' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
|
||||||
|
GetTypeWrapper("MyClass");
|
||||||
|
|
||||||
|
class MyClass { }
|
||||||
|
|
||||||
|
// May be defined in another assembly, so at runtime Type.GetType will look in that assembly for "MyClass".
|
||||||
|
void GetTypeWrapper([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string typeName)
|
||||||
|
{
|
||||||
|
var type = Type.GetType(typeName);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Single-File Warning Codes
|
## Single-File Warning Codes
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<PublishTrimmed>true</PublishTrimmed>
|
<PublishTrimmed>true</PublishTrimmed>
|
||||||
<!-- Suppress trimming warnings as these are tests -->
|
<!-- Suppress trimming warnings as these are tests -->
|
||||||
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
||||||
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
|
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
|
||||||
|
|
||||||
<!-- Reduce library test app size by trimming framework library features -->
|
<!-- Reduce library test app size by trimming framework library features -->
|
||||||
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>
|
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
<IlcSdkPath>$(CoreCLRAotSdkDir)</IlcSdkPath>
|
<IlcSdkPath>$(CoreCLRAotSdkDir)</IlcSdkPath>
|
||||||
<IlcFrameworkPath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkPath>
|
<IlcFrameworkPath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkPath>
|
||||||
<IlcFrameworkNativePath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkNativePath>
|
<IlcFrameworkNativePath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkNativePath>
|
||||||
<NoWarn>$(NoWarn);IL1005;IL2105;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
|
<NoWarn>$(NoWarn);IL1005;IL2122;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
|
||||||
<TrimMode>partial</TrimMode>
|
<TrimMode>partial</TrimMode>
|
||||||
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
||||||
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
<TrimmerSingleWarn>false</TrimmerSingleWarn>
|
||||||
|
|
|
@ -36,13 +36,18 @@ namespace Internal.TypeSystem
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name, ModuleDesc callingModule,
|
public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name, ModuleDesc callingModule,
|
||||||
TypeSystemContext context, List<ModuleDesc> referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary)
|
TypeSystemContext context, List<ModuleDesc> referencedModules, bool needsAssemblyName, out bool failedBecauseNotFullyQualified)
|
||||||
{
|
{
|
||||||
typeWasNotFoundInAssemblyNorBaseLibrary = false;
|
failedBecauseNotFullyQualified = false;
|
||||||
|
|
||||||
if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions))
|
if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions))
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
if (needsAssemblyName && !IsFullyQualified(parsed))
|
||||||
|
{
|
||||||
|
failedBecauseNotFullyQualified = true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
TypeNameResolver resolver = new()
|
TypeNameResolver resolver = new()
|
||||||
{
|
{
|
||||||
_context = context,
|
_context = context,
|
||||||
|
@ -52,8 +57,33 @@ namespace Internal.TypeSystem
|
||||||
|
|
||||||
TypeDesc type = resolver.Resolve(parsed);
|
TypeDesc type = resolver.Resolve(parsed);
|
||||||
|
|
||||||
typeWasNotFoundInAssemblyNorBaseLibrary = resolver._typeWasNotFoundInAssemblyNorBaseLibrary;
|
|
||||||
return type;
|
return type;
|
||||||
|
|
||||||
|
static bool IsFullyQualified(TypeName typeName)
|
||||||
|
{
|
||||||
|
if (typeName.AssemblyName is null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
|
||||||
|
{
|
||||||
|
return IsFullyQualified(typeName.GetElementType());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeName.IsConstructedGenericType)
|
||||||
|
{
|
||||||
|
foreach (var typeArgument in typeName.GetGenericArguments())
|
||||||
|
{
|
||||||
|
if (!IsFullyQualified(typeArgument))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct TypeNameResolver
|
private struct TypeNameResolver
|
||||||
|
@ -64,7 +94,6 @@ namespace Internal.TypeSystem
|
||||||
internal Func<ModuleDesc, string, MetadataType> _canonResolver;
|
internal Func<ModuleDesc, string, MetadataType> _canonResolver;
|
||||||
|
|
||||||
internal List<ModuleDesc> _referencedModules;
|
internal List<ModuleDesc> _referencedModules;
|
||||||
internal bool _typeWasNotFoundInAssemblyNorBaseLibrary;
|
|
||||||
|
|
||||||
internal TypeDesc Resolve(TypeName typeName)
|
internal TypeDesc Resolve(TypeName typeName)
|
||||||
{
|
{
|
||||||
|
@ -136,8 +165,6 @@ namespace Internal.TypeSystem
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_typeWasNotFoundInAssemblyNorBaseLibrary = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_throwIfNotFound)
|
if (_throwIfNotFound)
|
||||||
|
|
|
@ -89,12 +89,13 @@ namespace ILCompiler.Dataflow
|
||||||
|
|
||||||
List<ModuleDesc> referencedModules = new();
|
List<ModuleDesc> referencedModules = new();
|
||||||
TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
|
TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
|
||||||
referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary);
|
referencedModules, needsAssemblyName, out bool failedBecauseNotFullyQualified);
|
||||||
if (foundType == null)
|
if (foundType == null)
|
||||||
{
|
{
|
||||||
if (needsAssemblyName && typeWasNotFoundInAssemblyNorBaseLibrary)
|
if (failedBecauseNotFullyQualified)
|
||||||
diagnosticContext.AddDiagnostic(DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeName);
|
{
|
||||||
|
diagnosticContext.AddDiagnostic(DiagnosticId.TypeNameIsNotAssemblyQualified, typeName);
|
||||||
|
}
|
||||||
type = default;
|
type = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ using Internal.TypeSystem.Ecma;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using Mono.Cecil.Cil;
|
using Mono.Cecil.Cil;
|
||||||
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
||||||
|
using Mono.Linker.Tests.Cases.Expectations.Helpers;
|
||||||
using Mono.Linker.Tests.Extensions;
|
using Mono.Linker.Tests.Extensions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
using MetadataType = Internal.TypeSystem.MetadataType;
|
using MetadataType = Internal.TypeSystem.MetadataType;
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Program
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static int Main(string[] args)
|
static int Main(string[] args)
|
||||||
{
|
{
|
||||||
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider");
|
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider, project");
|
||||||
if (!RunTest(attr))
|
if (!RunTest(attr))
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -53,7 +53,7 @@ class Program
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy")]
|
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy, project")]
|
||||||
public class MyClassWithProxyString
|
public class MyClassWithProxyString
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
|
@ -113,8 +113,8 @@ class Program
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer")]
|
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer, project")]
|
||||||
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2", "Program+MyClassWithVisualizerStringVisualizerObjectSource")]
|
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2, project", "Program+MyClassWithVisualizerStringVisualizerObjectSource, project")]
|
||||||
public class MyClassWithVisualizerString
|
public class MyClassWithVisualizerString
|
||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<PropertyGroup Condition="'$(EnableAggressiveTrimming)' == 'true'">
|
<PropertyGroup Condition="'$(EnableAggressiveTrimming)' == 'true'">
|
||||||
<!-- Suppress trimming warnings as these are tests -->
|
<!-- Suppress trimming warnings as these are tests -->
|
||||||
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
||||||
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
|
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- This .targets file is also imported by the runtime Trimming tests, and we want to be able to manually configure trimming in them so this
|
<!-- This .targets file is also imported by the runtime Trimming tests, and we want to be able to manually configure trimming in them so this
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace ILLink.Shared
|
||||||
_unused_RearrangedXmlWarning2 = 2021,
|
_unused_RearrangedXmlWarning2 = 2021,
|
||||||
XmlCouldNotFindMatchingConstructorForCustomAttribute = 2022,
|
XmlCouldNotFindMatchingConstructorForCustomAttribute = 2022,
|
||||||
XmlMoreThanOneReturnElementForMethod = 2023,
|
XmlMoreThanOneReturnElementForMethod = 2023,
|
||||||
XmlMoreThanOneValyForParameterOfMethod = 2024,
|
XmlMoreThanOneValueForParameterOfMethod = 2024,
|
||||||
XmlDuplicatePreserveMember = 2025,
|
XmlDuplicatePreserveMember = 2025,
|
||||||
RequiresUnreferencedCode = 2026,
|
RequiresUnreferencedCode = 2026,
|
||||||
AttributeShouldOnlyBeUsedOnceOnMember = 2027,
|
AttributeShouldOnlyBeUsedOnceOnMember = 2027,
|
||||||
|
@ -169,7 +169,7 @@ namespace ILLink.Shared
|
||||||
InvalidIsTrimmableValue = 2102,
|
InvalidIsTrimmableValue = 2102,
|
||||||
PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined = 2103,
|
PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined = 2103,
|
||||||
AssemblyProducedTrimWarnings = 2104,
|
AssemblyProducedTrimWarnings = 2104,
|
||||||
TypeWasNotFoundInAssemblyNorBaseLibrary = 2105,
|
_unused_TypeWasNotFoundInAssemblyNorBaseLibrary = 2105,
|
||||||
DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings = 2106,
|
DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings = 2106,
|
||||||
MethodsAreAssociatedWithStateMachine = 2107,
|
MethodsAreAssociatedWithStateMachine = 2107,
|
||||||
InvalidScopeInUnconditionalSuppressMessage = 2108,
|
InvalidScopeInUnconditionalSuppressMessage = 2108,
|
||||||
|
@ -186,6 +186,7 @@ namespace ILLink.Shared
|
||||||
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMember = 2119,
|
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMember = 2119,
|
||||||
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMemberOnBase = 2120,
|
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMemberOnBase = 2120,
|
||||||
RedundantSuppression = 2121,
|
RedundantSuppression = 2121,
|
||||||
|
TypeNameIsNotAssemblyQualified = 2122,
|
||||||
|
|
||||||
// Single-file diagnostic ids.
|
// Single-file diagnostic ids.
|
||||||
AvoidAssemblyLocationInSingleFile = 3000,
|
AvoidAssemblyLocationInSingleFile = 3000,
|
||||||
|
|
|
@ -525,10 +525,10 @@
|
||||||
<data name="XmlMoreThanOneReturnElementForMethodMessage" xml:space="preserve">
|
<data name="XmlMoreThanOneReturnElementForMethodMessage" xml:space="preserve">
|
||||||
<value>There is more than one 'return' child element specified for method '{0}'.</value>
|
<value>There is more than one 'return' child element specified for method '{0}'.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XmlMoreThanOneValyForParameterOfMethodTitle" xml:space="preserve">
|
<data name="XmlMoreThanOneValueForParameterOfMethodTitle" xml:space="preserve">
|
||||||
<value>Method has more than one parameter for the XML element 'parameter'. There can only be one value specified for each parameter.</value>
|
<value>Method has more than one parameter for the XML element 'parameter'. There can only be one value specified for each parameter.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XmlMoreThanOneValyForParameterOfMethodMessage" xml:space="preserve">
|
<data name="XmlMoreThanOneValueForParameterOfMethodMessage" xml:space="preserve">
|
||||||
<value>More than one value specified for parameter '{0}' of method '{1}'.</value>
|
<value>More than one value specified for parameter '{0}' of method '{1}'.</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="XmlDuplicatePreserveMemberTitle" xml:space="preserve">
|
<data name="XmlDuplicatePreserveMemberTitle" xml:space="preserve">
|
||||||
|
@ -1209,4 +1209,10 @@
|
||||||
<data name="InvalidFeatureGuardTitle" xml:space="preserve">
|
<data name="InvalidFeatureGuardTitle" xml:space="preserve">
|
||||||
<value>Invalid FeatureGuardAttribute.</value>
|
<value>Invalid FeatureGuardAttribute.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="TypeNameIsNotAssemblyQualifiedMessage" xml:space="preserve">
|
||||||
|
<value>Type '{0}' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.</value>
|
||||||
|
</data>
|
||||||
|
<data name="TypeNameIsNotAssemblyQualifiedTitle" xml:space="preserve">
|
||||||
|
<value>Type name is not assembly qualified.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
|
|
@ -44,7 +44,7 @@ namespace ILLink.Shared.TrimAnalysis
|
||||||
} else if (uniqueValue is SystemTypeValue systemTypeValue) {
|
} else if (uniqueValue is SystemTypeValue systemTypeValue) {
|
||||||
MarkTypeForDynamicallyAccessedMembers (systemTypeValue.RepresentedType, targetValue.DynamicallyAccessedMemberTypes);
|
MarkTypeForDynamicallyAccessedMembers (systemTypeValue.RepresentedType, targetValue.DynamicallyAccessedMemberTypes);
|
||||||
} else if (uniqueValue is KnownStringValue knownStringValue) {
|
} else if (uniqueValue is KnownStringValue knownStringValue) {
|
||||||
if (!TryResolveTypeNameAndMark (knownStringValue.Contents, true, out TypeProxy foundType)) {
|
if (!TryResolveTypeNameAndMark (knownStringValue.Contents, needsAssemblyName: true, out TypeProxy foundType)) {
|
||||||
// Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back.
|
// Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back.
|
||||||
} else {
|
} else {
|
||||||
MarkTypeForDynamicallyAccessedMembers (foundType, targetValue.DynamicallyAccessedMemberTypes);
|
MarkTypeForDynamicallyAccessedMembers (foundType, targetValue.DynamicallyAccessedMemberTypes);
|
||||||
|
|
|
@ -1509,6 +1509,12 @@
|
||||||
<Left>ref/net9.0/illink.dll</Left>
|
<Left>ref/net9.0/illink.dll</Left>
|
||||||
<Right>lib/net9.0/illink.dll</Right>
|
<Right>lib/net9.0/illink.dll</Right>
|
||||||
</Suppression>
|
</Suppression>
|
||||||
|
<Suppression>
|
||||||
|
<DiagnosticId>CP0002</DiagnosticId>
|
||||||
|
<Target>M:Mono.Linker.LinkContext.get_SystemModuleName</Target>
|
||||||
|
<Left>ref/net9.0/illink.dll</Left>
|
||||||
|
<Right>lib/net9.0/illink.dll</Right>
|
||||||
|
</Suppression>
|
||||||
<Suppression>
|
<Suppression>
|
||||||
<DiagnosticId>CP0002</DiagnosticId>
|
<DiagnosticId>CP0002</DiagnosticId>
|
||||||
<Target>M:Mono.Linker.LinkContext.set_KeepComInterfaces(System.Boolean)</Target>
|
<Target>M:Mono.Linker.LinkContext.set_KeepComInterfaces(System.Boolean)</Target>
|
||||||
|
@ -1521,6 +1527,12 @@
|
||||||
<Left>ref/net9.0/illink.dll</Left>
|
<Left>ref/net9.0/illink.dll</Left>
|
||||||
<Right>lib/net9.0/illink.dll</Right>
|
<Right>lib/net9.0/illink.dll</Right>
|
||||||
</Suppression>
|
</Suppression>
|
||||||
|
<Suppression>
|
||||||
|
<DiagnosticId>CP0002</DiagnosticId>
|
||||||
|
<Target>M:Mono.Linker.LinkContext.set_SystemModuleName(System.String)</Target>
|
||||||
|
<Left>ref/net9.0/illink.dll</Left>
|
||||||
|
<Right>lib/net9.0/illink.dll</Right>
|
||||||
|
</Suppression>
|
||||||
<Suppression>
|
<Suppression>
|
||||||
<DiagnosticId>CP0008</DiagnosticId>
|
<DiagnosticId>CP0008</DiagnosticId>
|
||||||
<Target>T:Mono.Linker.LinkContext</Target>
|
<Target>T:Mono.Linker.LinkContext</Target>
|
||||||
|
|
|
@ -72,7 +72,7 @@ namespace Mono.Linker.Steps
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAttribute? customAttribute = CreateCustomAttribute (attributeNav, attributeType);
|
CustomAttribute? customAttribute = CreateCustomAttribute (attributeNav, attributeType, provider);
|
||||||
if (customAttribute != null) {
|
if (customAttribute != null) {
|
||||||
_context.LogMessage ($"Assigning external custom attribute '{FormatCustomAttribute (customAttribute)}' instance to '{provider}'.");
|
_context.LogMessage ($"Assigning external custom attribute '{FormatCustomAttribute (customAttribute)}' instance to '{provider}'.");
|
||||||
customAttributesBuilder.Add (customAttribute);
|
customAttributesBuilder.Add (customAttribute);
|
||||||
|
@ -153,9 +153,9 @@ namespace Mono.Linker.Steps
|
||||||
return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition = td;
|
return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition = td;
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAttribute? CreateCustomAttribute (XPathNavigator nav, TypeDefinition attributeType)
|
CustomAttribute? CreateCustomAttribute (XPathNavigator nav, TypeDefinition attributeType, ICustomAttributeProvider provider)
|
||||||
{
|
{
|
||||||
CustomAttributeArgument[] arguments = ReadCustomAttributeArguments (nav, attributeType);
|
CustomAttributeArgument[] arguments = ReadCustomAttributeArguments (nav, provider);
|
||||||
|
|
||||||
MethodDefinition? constructor = FindBestMatchingConstructor (attributeType, arguments);
|
MethodDefinition? constructor = FindBestMatchingConstructor (attributeType, arguments);
|
||||||
if (constructor == null) {
|
if (constructor == null) {
|
||||||
|
@ -223,12 +223,12 @@ namespace Mono.Linker.Steps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAttributeArgument[] ReadCustomAttributeArguments (XPathNavigator nav, TypeDefinition attributeType)
|
CustomAttributeArgument[] ReadCustomAttributeArguments (XPathNavigator nav, ICustomAttributeProvider provider)
|
||||||
{
|
{
|
||||||
ArrayBuilder<CustomAttributeArgument> args = default;
|
ArrayBuilder<CustomAttributeArgument> args = default;
|
||||||
|
|
||||||
foreach (XPathNavigator argumentNav in nav.SelectChildren ("argument", string.Empty)) {
|
foreach (XPathNavigator argumentNav in nav.SelectChildren ("argument", string.Empty)) {
|
||||||
CustomAttributeArgument? caa = ReadCustomAttributeArgument (argumentNav, attributeType);
|
CustomAttributeArgument? caa = ReadCustomAttributeArgument (argumentNav, provider);
|
||||||
if (caa is not null)
|
if (caa is not null)
|
||||||
args.Add (caa.Value);
|
args.Add (caa.Value);
|
||||||
}
|
}
|
||||||
|
@ -236,9 +236,9 @@ namespace Mono.Linker.Steps
|
||||||
return args.ToArray () ?? Array.Empty<CustomAttributeArgument> ();
|
return args.ToArray () ?? Array.Empty<CustomAttributeArgument> ();
|
||||||
}
|
}
|
||||||
|
|
||||||
CustomAttributeArgument? ReadCustomAttributeArgument (XPathNavigator nav, IMemberDefinition memberWithAttribute)
|
CustomAttributeArgument? ReadCustomAttributeArgument (XPathNavigator nav, ICustomAttributeProvider provider)
|
||||||
{
|
{
|
||||||
TypeReference? typeref = ResolveArgumentType (nav, memberWithAttribute);
|
TypeReference? typeref = ResolveArgumentType (nav, provider);
|
||||||
if (typeref is null)
|
if (typeref is null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -295,8 +295,8 @@ namespace Mono.Linker.Steps
|
||||||
if (!typeref.IsTypeOf (WellKnownType.System_Type))
|
if (!typeref.IsTypeOf (WellKnownType.System_Type))
|
||||||
goto default;
|
goto default;
|
||||||
|
|
||||||
var diagnosticContext = new DiagnosticContext (new MessageOrigin (memberWithAttribute), diagnosticsEnabled: true, _context);
|
var diagnosticContext = new DiagnosticContext (new MessageOrigin (provider), diagnosticsEnabled: true, _context);
|
||||||
if (!_context.TypeNameResolver.TryResolveTypeName (svalue, diagnosticContext, out TypeReference? type, out _)) {
|
if (!_context.TypeNameResolver.TryResolveTypeName (svalue, diagnosticContext, out TypeReference? type, out _, needsAssemblyName: false)) {
|
||||||
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.CouldNotResolveCustomAttributeTypeValue, svalue);
|
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.CouldNotResolveCustomAttributeTypeValue, svalue);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ namespace Mono.Linker.Steps
|
||||||
var arrayArgumentIterator = nav.SelectChildren ("argument", string.Empty);
|
var arrayArgumentIterator = nav.SelectChildren ("argument", string.Empty);
|
||||||
ArrayBuilder<CustomAttributeArgument> elements = default;
|
ArrayBuilder<CustomAttributeArgument> elements = default;
|
||||||
foreach (XPathNavigator elementNav in arrayArgumentIterator) {
|
foreach (XPathNavigator elementNav in arrayArgumentIterator) {
|
||||||
if (ReadCustomAttributeArgument (elementNav, memberWithAttribute) is CustomAttributeArgument arg) {
|
if (ReadCustomAttributeArgument (elementNav, provider) is CustomAttributeArgument arg) {
|
||||||
// To match Cecil, elements of a list that are subclasses of the list type must be boxed in the base type
|
// To match Cecil, elements of a list that are subclasses of the list type must be boxed in the base type
|
||||||
// e.g. object[] { 73 } translates to Cecil.CAA { Type: object[] : Value: CAA{ Type: object, Value: CAA{ Type: int, Value: 73} } }
|
// e.g. object[] { 73 } translates to Cecil.CAA { Type: object[] : Value: CAA{ Type: object, Value: CAA{ Type: int, Value: 73} } }
|
||||||
if (arg.Type == elementType) {
|
if (arg.Type == elementType) {
|
||||||
|
@ -338,14 +338,14 @@ namespace Mono.Linker.Steps
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
TypeReference? ResolveArgumentType (XPathNavigator nav, IMemberDefinition memberWithAttribute)
|
TypeReference? ResolveArgumentType (XPathNavigator nav, ICustomAttributeProvider provider)
|
||||||
{
|
{
|
||||||
string typeName = GetAttribute (nav, "type");
|
string typeName = GetAttribute (nav, "type");
|
||||||
if (string.IsNullOrEmpty (typeName))
|
if (string.IsNullOrEmpty (typeName))
|
||||||
typeName = "System.String";
|
typeName = "System.String";
|
||||||
|
|
||||||
var diagnosticContext = new DiagnosticContext (new MessageOrigin (memberWithAttribute), diagnosticsEnabled: true, _context);
|
var diagnosticContext = new DiagnosticContext (new MessageOrigin (provider), diagnosticsEnabled: true, _context);
|
||||||
if (!_context.TypeNameResolver.TryResolveTypeName (typeName, diagnosticContext, out TypeReference? typeref, out _)) {
|
if (!_context.TypeNameResolver.TryResolveTypeName (typeName, diagnosticContext, out TypeReference? typeref, out _, needsAssemblyName: false)) {
|
||||||
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.TypeUsedWithAttributeValueCouldNotBeFound, typeName, nav.Value);
|
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.TypeUsedWithAttributeValueCouldNotBeFound, typeName, nav.Value);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -501,7 +501,7 @@ namespace Mono.Linker.Steps
|
||||||
foreach (ParameterDefinition parameter in method.Parameters) {
|
foreach (ParameterDefinition parameter in method.Parameters) {
|
||||||
if (paramName == parameter.Name) {
|
if (paramName == parameter.Name) {
|
||||||
if (parameter.HasCustomAttributes || _attributeInfo.CustomAttributes.ContainsKey (parameter))
|
if (parameter.HasCustomAttributes || _attributeInfo.CustomAttributes.ContainsKey (parameter))
|
||||||
LogWarning (parameterNav, DiagnosticId.XmlMoreThanOneValyForParameterOfMethod, paramName, method.GetDisplayName ());
|
LogWarning (parameterNav, DiagnosticId.XmlMoreThanOneValueForParameterOfMethod, paramName, method.GetDisplayName ());
|
||||||
_attributeInfo.AddCustomAttributes (parameter, attributes, origins);
|
_attributeInfo.AddCustomAttributes (parameter, attributes, origins);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -513,11 +513,15 @@ namespace Mono.Linker.Steps
|
||||||
|
|
||||||
void ProcessReturnParameters (MethodDefinition method, XPathNavigator nav)
|
void ProcessReturnParameters (MethodDefinition method, XPathNavigator nav)
|
||||||
{
|
{
|
||||||
|
Debug.Assert (_attributeInfo != null);
|
||||||
bool firstAppearance = true;
|
bool firstAppearance = true;
|
||||||
foreach (XPathNavigator returnNav in nav.SelectChildren ("return", string.Empty)) {
|
foreach (XPathNavigator returnNav in nav.SelectChildren ("return", string.Empty)) {
|
||||||
if (firstAppearance) {
|
if (firstAppearance) {
|
||||||
firstAppearance = false;
|
firstAppearance = false;
|
||||||
PopulateAttributeInfo (method.MethodReturnType, returnNav);
|
var (attributes, origins) = ProcessAttributes (returnNav, method);
|
||||||
|
if (attributes != null && origins != null) {
|
||||||
|
_attributeInfo.AddCustomAttributes (method.MethodReturnType, attributes, origins);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LogWarning (returnNav, DiagnosticId.XmlMoreThanOneReturnElementForMethod, method.GetDisplayName ());
|
LogWarning (returnNav, DiagnosticId.XmlMoreThanOneReturnElementForMethod, method.GetDisplayName ());
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,10 +45,6 @@ using Mono.Cecil.Cil;
|
||||||
using Mono.Collections.Generic;
|
using Mono.Collections.Generic;
|
||||||
using Mono.Linker.Dataflow;
|
using Mono.Linker.Dataflow;
|
||||||
|
|
||||||
using AssemblyNameInfo = System.Reflection.Metadata.AssemblyNameInfo;
|
|
||||||
using TypeName = System.Reflection.Metadata.TypeName;
|
|
||||||
using TypeNameParseOptions = System.Reflection.Metadata.TypeNameParseOptions;
|
|
||||||
|
|
||||||
namespace Mono.Linker.Steps
|
namespace Mono.Linker.Steps
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ namespace Mono.Linker
|
||||||
int? _targetRuntime;
|
int? _targetRuntime;
|
||||||
|
|
||||||
readonly AssemblyResolver _resolver;
|
readonly AssemblyResolver _resolver;
|
||||||
readonly TypeNameResolver _typeNameResolver;
|
TypeNameResolver? _typeNameResolver;
|
||||||
|
|
||||||
readonly AnnotationStore _annotations;
|
readonly AnnotationStore _annotations;
|
||||||
readonly CustomAttributeSource _customAttributes;
|
readonly CustomAttributeSource _customAttributes;
|
||||||
|
@ -146,9 +146,8 @@ namespace Mono.Linker
|
||||||
get { return _resolver; }
|
get { return _resolver; }
|
||||||
}
|
}
|
||||||
|
|
||||||
internal TypeNameResolver TypeNameResolver {
|
internal TypeNameResolver TypeNameResolver
|
||||||
get { return _typeNameResolver; }
|
=> _typeNameResolver ??= new TypeNameResolver (this, this);
|
||||||
}
|
|
||||||
|
|
||||||
public ISymbolReaderProvider SymbolReaderProvider { get; set; }
|
public ISymbolReaderProvider SymbolReaderProvider { get; set; }
|
||||||
|
|
||||||
|
@ -205,7 +204,6 @@ namespace Mono.Linker
|
||||||
_logger = logger ?? throw new ArgumentNullException (nameof (logger));
|
_logger = logger ?? throw new ArgumentNullException (nameof (logger));
|
||||||
|
|
||||||
_resolver = factory.CreateResolver (this);
|
_resolver = factory.CreateResolver (this);
|
||||||
_typeNameResolver = new TypeNameResolver (this, this);
|
|
||||||
_actions = new Dictionary<string, AssemblyAction> ();
|
_actions = new Dictionary<string, AssemblyAction> ();
|
||||||
_parameters = new Dictionary<string, string> (StringComparer.Ordinal);
|
_parameters = new Dictionary<string, string> (StringComparer.Ordinal);
|
||||||
_customAttributes = new CustomAttributeSource (this);
|
_customAttributes = new CustomAttributeSource (this);
|
||||||
|
@ -973,7 +971,7 @@ namespace Mono.Linker
|
||||||
public TypeDefinition? TryResolve (AssemblyDefinition assembly, string typeNameString)
|
public TypeDefinition? TryResolve (AssemblyDefinition assembly, string typeNameString)
|
||||||
{
|
{
|
||||||
// It could be cached if it shows up on fast path
|
// It could be cached if it shows up on fast path
|
||||||
return _typeNameResolver.TryResolveTypeName (assembly, typeNameString, out TypeReference? typeReference, out _)
|
return TypeNameResolver.TryResolveTypeName (assembly, typeNameString, out TypeReference? typeReference, out _)
|
||||||
? TryResolve (typeReference)
|
? TryResolve (typeReference)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,8 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using ILLink.Shared;
|
using ILLink.Shared;
|
||||||
using ILLink.Shared.TrimAnalysis;
|
using ILLink.Shared.TrimAnalysis;
|
||||||
using Mono.Cecil;
|
using Mono.Cecil;
|
||||||
using Mono.Linker;
|
|
||||||
|
|
||||||
using TypeName = System.Reflection.Metadata.TypeName;
|
using TypeName = System.Reflection.Metadata.TypeName;
|
||||||
using AssemblyNameInfo = System.Reflection.Metadata.AssemblyNameInfo;
|
|
||||||
|
|
||||||
namespace Mono.Linker
|
namespace Mono.Linker
|
||||||
{
|
{
|
||||||
|
@ -21,7 +19,7 @@ namespace Mono.Linker
|
||||||
in DiagnosticContext diagnosticContext,
|
in DiagnosticContext diagnosticContext,
|
||||||
[NotNullWhen (true)] out TypeReference? typeReference,
|
[NotNullWhen (true)] out TypeReference? typeReference,
|
||||||
[NotNullWhen (true)] out List<TypeResolutionRecord>? typeResolutionRecords,
|
[NotNullWhen (true)] out List<TypeResolutionRecord>? typeResolutionRecords,
|
||||||
bool needsAssemblyName = true)
|
bool needsAssemblyName)
|
||||||
{
|
{
|
||||||
typeReference = null;
|
typeReference = null;
|
||||||
typeResolutionRecords = null;
|
typeResolutionRecords = null;
|
||||||
|
@ -31,28 +29,16 @@ namespace Mono.Linker
|
||||||
if (!TypeName.TryParse (typeNameString, out TypeName? parsedTypeName, s_typeNameParseOptions))
|
if (!TypeName.TryParse (typeNameString, out TypeName? parsedTypeName, s_typeNameParseOptions))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
typeResolutionRecords = new List<TypeResolutionRecord> ();
|
if (needsAssemblyName && !IsFullyQualified (parsedTypeName)) {
|
||||||
AssemblyDefinition? typeAssembly;
|
diagnosticContext.AddDiagnostic (DiagnosticId.TypeNameIsNotAssemblyQualified, typeNameString);
|
||||||
if (parsedTypeName.AssemblyName is AssemblyNameInfo assemblyName) {
|
return false;
|
||||||
typeAssembly = _assemblyResolver.TryResolve (assemblyName.Name);
|
|
||||||
if (typeAssembly is null) {
|
|
||||||
typeResolutionRecords = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
typeReference = ResolveTypeName (typeAssembly, parsedTypeName, typeResolutionRecords);
|
|
||||||
if (typeReference == null) {
|
|
||||||
typeResolutionRecords = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return typeReference != null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If parsedTypeName doesn't have an assembly name in it but it does have a namespace,
|
// If parsedTypeName doesn't have an assembly name in it but it does have a namespace,
|
||||||
// search for the type in the calling object's assembly. If not found, look in the core
|
// search for the type in the calling object's assembly. If not found, look in the core
|
||||||
// assembly.
|
// assembly.
|
||||||
ICustomAttributeProvider? provider = diagnosticContext.Origin.Provider;
|
ICustomAttributeProvider? provider = diagnosticContext.Origin.Provider;
|
||||||
typeAssembly = provider switch {
|
AssemblyDefinition? referencingAssembly = provider switch {
|
||||||
AssemblyDefinition asm => asm,
|
AssemblyDefinition asm => asm,
|
||||||
TypeDefinition type => type.Module?.Assembly,
|
TypeDefinition type => type.Module?.Assembly,
|
||||||
IMemberDefinition member => member.DeclaringType.Module.Assembly,
|
IMemberDefinition member => member.DeclaringType.Module.Assembly,
|
||||||
|
@ -60,30 +46,29 @@ namespace Mono.Linker
|
||||||
_ => throw new NotSupportedException ()
|
_ => throw new NotSupportedException ()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference, typeResolutionRecords))
|
if (referencingAssembly is null)
|
||||||
return true;
|
return false;
|
||||||
|
|
||||||
// If type is not found in the caller's assembly, try in core assembly.
|
typeResolutionRecords = new List<TypeResolutionRecord> ();
|
||||||
typeAssembly = _assemblyResolver.TryResolve (PlatformAssemblies.CoreLib);
|
typeReference = ResolveTypeName (referencingAssembly, parsedTypeName, typeResolutionRecords);
|
||||||
if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference, typeResolutionRecords))
|
return typeReference != null;
|
||||||
return true;
|
|
||||||
|
|
||||||
// It is common to use Type.GetType for looking if a type is available.
|
static bool IsFullyQualified (TypeName typeName)
|
||||||
// If no type was found only warn and return null.
|
|
||||||
if (needsAssemblyName && provider != null)
|
|
||||||
diagnosticContext.AddDiagnostic (DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeNameString);
|
|
||||||
|
|
||||||
typeResolutionRecords = null;
|
|
||||||
return false;
|
|
||||||
|
|
||||||
bool TryResolveTypeName (AssemblyDefinition assemblyDefinition, TypeName? typeName, [NotNullWhen (true)] out TypeReference? typeReference, List<TypeResolutionRecord> typeResolutionRecords)
|
|
||||||
{
|
{
|
||||||
typeReference = null;
|
if (typeName.AssemblyName is null)
|
||||||
if (assemblyDefinition == null)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
typeReference = ResolveTypeName (assemblyDefinition, typeName, typeResolutionRecords);
|
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
|
||||||
return typeReference != null;
|
return IsFullyQualified (typeName.GetElementType ());
|
||||||
|
|
||||||
|
if (typeName.IsConstructedGenericType) {
|
||||||
|
foreach (var typeArgument in typeName.GetGenericArguments ()) {
|
||||||
|
if (!IsFullyQualified (typeArgument))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,19 @@ namespace Mono.Linker
|
||||||
return resolvedType;
|
return resolvedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If it didn't resolve and wasn't assembly-qualified, we also try core library
|
||||||
|
var coreLibrary = _metadataResolver.TryResolve (originalAssembly.MainModule.TypeSystem.Object)?.Module.Assembly;
|
||||||
|
if (coreLibrary is null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (topLevelTypeName.AssemblyName == null && assembly != coreLibrary) {
|
||||||
|
resolvedType = GetSimpleTypeFromModule (typeName, coreLibrary.MainModule);
|
||||||
|
if (resolvedType != null) {
|
||||||
|
typeResolutionRecords.Add (new (coreLibrary, resolvedType));
|
||||||
|
return resolvedType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
TypeDefinition? GetSimpleTypeFromModule (TypeName typeName, ModuleDefinition module)
|
TypeDefinition? GetSimpleTypeFromModule (TypeName typeName, ModuleDefinition module)
|
||||||
|
|
|
@ -45,8 +45,8 @@ namespace Mono.Linker.Tests.Cases.ComponentModel
|
||||||
[Kept]
|
[Kept]
|
||||||
[KeptAttributeAttribute (typeof (TypeConverterAttribute))]
|
[KeptAttributeAttribute (typeof (TypeConverterAttribute))]
|
||||||
[KeptBackingField]
|
[KeptBackingField]
|
||||||
[ExpectedWarning ("IL2105",
|
[ExpectedWarning ("IL2122",
|
||||||
"Type 'NonExistentType' was not found in the caller assembly nor in the base library. " +
|
"Type 'NonExistentType' is not assembly qualified. " +
|
||||||
"Type name strings used for dynamically accessing a type should be assembly qualified.")]
|
"Type name strings used for dynamically accessing a type should be assembly qualified.")]
|
||||||
public string Bar { [Kept] get; set; }
|
public string Bar { [Kept] get; set; }
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
[Kept]
|
[Kept]
|
||||||
static void TestFromStringContantWithAnnotation ()
|
static void TestFromStringContantWithAnnotation ()
|
||||||
{
|
{
|
||||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithAnnotationTestType");
|
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithAnnotationTestType, test");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
|
@ -188,10 +188,19 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
[UnconditionalSuppressMessage("test", "IL3050", Justification = "The test applies DAM on System.Array, which contains CreateInstance method which has RDC on it.")]
|
[UnconditionalSuppressMessage("test", "IL3050", Justification = "The test applies DAM on System.Array, which contains CreateInstance method which has RDC on it.")]
|
||||||
static void TestFromStringConstantWithGeneric ()
|
static void TestFromStringConstantWithGeneric ()
|
||||||
{
|
{
|
||||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner]]");
|
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1["
|
||||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericTwoParameters`2[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerOne`1[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerInner],Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerTwo]");
|
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner, test]"
|
||||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWitGenericInnerMultiDimArray[,]]]");
|
+ "], test");
|
||||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithMultiDimArray[,]");
|
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericTwoParameters`2["
|
||||||
|
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerOne`1["
|
||||||
|
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerInner, test]"
|
||||||
|
+ "], test],"
|
||||||
|
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerTwo, test]"
|
||||||
|
+ "], test");
|
||||||
|
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1["
|
||||||
|
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWitGenericInnerMultiDimArray[,], test]"
|
||||||
|
+ "], test");
|
||||||
|
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithMultiDimArray[,], test");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
|
@ -205,7 +214,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
[Kept]
|
[Kept]
|
||||||
static void TestFromStringConstantWithGenericAndAssemblyQualified ()
|
static void TestFromStringConstantWithGenericAndAssemblyQualified ()
|
||||||
{
|
{
|
||||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericAndAssemblyQualified`1[[Mono.Linker.Tests.Cases.Expectations.Assertions.KeptAttribute,Mono.Linker.Tests.Cases.Expectations]]");
|
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericAndAssemblyQualified`1["
|
||||||
|
+ "[Mono.Linker.Tests.Cases.Expectations.Assertions.KeptAttribute, Mono.Linker.Tests.Cases.Expectations]"
|
||||||
|
+ "], test");
|
||||||
}
|
}
|
||||||
|
|
||||||
class InvalidAssemblyNameType
|
class InvalidAssemblyNameType
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
RequireNothing (type);
|
RequireNothing (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ExpectedWarning ("IL2105", "Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " + "Type name strings used for dynamically accessing a type should be assembly qualified.", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
[ExpectedWarning ("IL2122", "Type 'System.Invalid.TypeName' is not assembly qualified. " + "Type name strings used for dynamically accessing a type should be assembly qualified.", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
static void TestUnqualifiedTypeNameWarns ()
|
static void TestUnqualifiedTypeNameWarns ()
|
||||||
{
|
{
|
||||||
RequirePublicConstructors ("System.Invalid.TypeName");
|
RequirePublicConstructors ("System.Invalid.TypeName");
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
[KeptAttributeAttribute (typeof (KeepsPublicFieldsAttribute))]
|
[KeptAttributeAttribute (typeof (KeepsPublicFieldsAttribute))]
|
||||||
[KeptAttributeAttribute (typeof (TypeArrayAttribute))]
|
[KeptAttributeAttribute (typeof (TypeArrayAttribute))]
|
||||||
[KeepsPublicConstructor (typeof (ClassWithKeptPublicConstructor))]
|
[KeepsPublicConstructor (typeof (ClassWithKeptPublicConstructor))]
|
||||||
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods")]
|
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods, test")]
|
||||||
[KeepsPublicFields (null, null)]
|
[KeepsPublicFields (null, null)]
|
||||||
[TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })]
|
[TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })]
|
||||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2273")]
|
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2273")]
|
||||||
|
|
|
@ -40,9 +40,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||||
// Trimmer/NativeAot only for now - https://github.com/dotnet/linker/issues/2273
|
|
||||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")]
|
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods, test")]
|
||||||
public static void TestKeepsPublicMethodsString ()
|
public static void TestKeepsPublicMethodsString ()
|
||||||
{
|
{
|
||||||
typeof (AttributeFieldDataflow).GetMethod (nameof (TestKeepsPublicMethodsString)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
typeof (AttributeFieldDataflow).GetMethod (nameof (TestKeepsPublicMethodsString)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||||
// Trimmer/NativeAot only for now
|
// Trimmer/NativeAot only for now
|
||||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName")]
|
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName, test")]
|
||||||
public static void TestKeepsPublicMethodsByName ()
|
public static void TestKeepsPublicMethodsByName ()
|
||||||
{
|
{
|
||||||
typeof (AttributesOnMethod).GetMethod (nameof (TestKeepsPublicMethodsByName)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
typeof (AttributesOnMethod).GetMethod (nameof (TestKeepsPublicMethodsByName)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
||||||
|
@ -213,7 +213,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||||
// Trimmer/NativeAot only for now
|
// Trimmer/NativeAot only for now
|
||||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)]
|
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethodsKeptByName, test" : null)]
|
||||||
public static void Test ()
|
public static void Test ()
|
||||||
{
|
{
|
||||||
typeof (AttributeWithConditionalExpression).GetMethod ("Test").GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
typeof (AttributeWithConditionalExpression).GetMethod ("Test").GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
|
||||||
|
@ -225,11 +225,11 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
[Kept]
|
[Kept]
|
||||||
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
|
||||||
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)]
|
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethodsKeptByName, test" : null)]
|
||||||
public static int field;
|
public static int field;
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
class ClassWithKeptPublicMethods
|
class ClassWithKeptPublicMethodsKeptByName
|
||||||
{
|
{
|
||||||
[Kept]
|
[Kept]
|
||||||
[KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
|
[KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]
|
||||||
|
|
|
@ -1372,29 +1372,32 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
{
|
{
|
||||||
static void MethodWithAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] string typeName) { }
|
static void MethodWithAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] string typeName) { }
|
||||||
|
|
||||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
|
||||||
static void AnnotatedParameter ()
|
static void AnnotatedParameter ()
|
||||||
{
|
{
|
||||||
MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]");
|
MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||||
|
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
|
||||||
|
+ "]], test");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
|
||||||
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
||||||
static string AnnotatedReturnValue ()
|
static string AnnotatedReturnValue ()
|
||||||
{
|
{
|
||||||
return "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]";
|
return "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||||
|
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
|
||||||
|
+ "]], test";
|
||||||
}
|
}
|
||||||
|
|
||||||
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
||||||
static string _annotatedField;
|
static string _annotatedField;
|
||||||
|
|
||||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
|
||||||
static void AnnotatedField ()
|
static void AnnotatedField ()
|
||||||
{
|
{
|
||||||
_annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]";
|
_annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||||
|
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
|
||||||
|
+ "]], test";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Test ()
|
public static void Test ()
|
||||||
|
@ -1407,11 +1410,12 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
|
|
||||||
class TypeGetType
|
class TypeGetType
|
||||||
{
|
{
|
||||||
// Analyzer: https://github.com/dotnet/runtime/issues/95118
|
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
|
|
||||||
static void SpecificType ()
|
static void SpecificType ()
|
||||||
{
|
{
|
||||||
Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]");
|
Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
|
||||||
|
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod"
|
||||||
|
+ "]]");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Test ()
|
public static void Test ()
|
||||||
|
|
|
@ -3,12 +3,12 @@
|
||||||
{
|
{
|
||||||
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
|
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
|
||||||
}
|
}
|
||||||
.assembly 'library'
|
.assembly 'EscapedTypeNames'
|
||||||
{
|
{
|
||||||
.hash algorithm 0x00008004
|
.hash algorithm 0x00008004
|
||||||
.ver 1:0:0:0
|
.ver 1:0:0:0
|
||||||
}
|
}
|
||||||
.module library.dll
|
.module EscapedTypeNames.dll
|
||||||
|
|
||||||
// =============== CLASS MEMBERS DECLARATION ===================
|
// =============== CLASS MEMBERS DECLARATION ===================
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
|
||||||
|
namespace Mono.Linker.Tests.Cases.Reflection.Dependencies
|
||||||
|
{
|
||||||
|
public class RequireHelper
|
||||||
|
{
|
||||||
|
public static Type RequireType ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string type) {
|
||||||
|
return Type.GetType (type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TypeDefinedInSameAssemblyAsGetType {}
|
||||||
|
}
|
|
@ -4,16 +4,19 @@ using System.Reflection;
|
||||||
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
||||||
using Mono.Linker.Tests.Cases.Expectations.Helpers;
|
using Mono.Linker.Tests.Cases.Expectations.Helpers;
|
||||||
using Mono.Linker.Tests.Cases.Expectations.Metadata;
|
using Mono.Linker.Tests.Cases.Expectations.Metadata;
|
||||||
|
using Mono.Linker.Tests.Cases.Reflection.Dependencies;
|
||||||
|
|
||||||
namespace Mono.Linker.Tests.Cases.Reflection
|
namespace Mono.Linker.Tests.Cases.Reflection
|
||||||
{
|
{
|
||||||
[KeptMember (".cctor()")]
|
[KeptMember (".cctor()")]
|
||||||
[ExpectedNoWarnings ()]
|
[ExpectedNoWarnings ()]
|
||||||
[Define ("IL_ASSEMBLY_AVAILABLE")]
|
[Define ("IL_ASSEMBLY_AVAILABLE")]
|
||||||
[SetupCompileBefore ("library.dll", new[] { "Dependencies/EscapedTypeNames.il" })]
|
[SetupCompileBefore ("EscapedTypeNames.dll", new[] { "Dependencies/EscapedTypeNames.il" })]
|
||||||
[KeptTypeInAssembly ("library", "Library.Not\\+Nested")]
|
[SetupCompileBefore ("RequireHelper.dll", new[] { "Dependencies/RequireHelper.cs" })]
|
||||||
[KeptTypeInAssembly ("library", "Library.Not\\+Nested+Nes\\\\ted")]
|
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested")]
|
||||||
[KeptTypeInAssembly ("library", "Library.Not\\+Nested+Nes/ted")]
|
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested+Nes\\\\ted")]
|
||||||
|
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested+Nes/ted")]
|
||||||
|
[RemovedTypeInAssembly ("RequireHelper", typeof (TypeDefinedInSameAssemblyAsGetType))]
|
||||||
[KeptDelegateCacheField ("0", nameof (AssemblyResolver))]
|
[KeptDelegateCacheField ("0", nameof (AssemblyResolver))]
|
||||||
[KeptDelegateCacheField ("1", nameof (GetTypeFromAssembly))]
|
[KeptDelegateCacheField ("1", nameof (GetTypeFromAssembly))]
|
||||||
public class TypeUsedViaReflection
|
public class TypeUsedViaReflection
|
||||||
|
@ -31,8 +34,9 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
||||||
TestReference ();
|
TestReference ();
|
||||||
TestArray ();
|
TestArray ();
|
||||||
TestArrayOfArray ();
|
TestArrayOfArray ();
|
||||||
TestGenericArray ();
|
TestGenericInstantiation ();
|
||||||
TestGenericArrayFullString ();
|
TestGenericInstantiationFullString ();
|
||||||
|
TestGenericInstantiationOverCoreLib ();
|
||||||
TestMultiDimensionalArray ();
|
TestMultiDimensionalArray ();
|
||||||
TestMultiDimensionalArrayFullString ();
|
TestMultiDimensionalArrayFullString ();
|
||||||
TestMultiDimensionalArrayAsmName ();
|
TestMultiDimensionalArrayAsmName ();
|
||||||
|
@ -55,6 +59,7 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
||||||
|
|
||||||
TestInvalidTypeCombination ();
|
TestInvalidTypeCombination ();
|
||||||
TestEscapedTypeName ();
|
TestEscapedTypeName ();
|
||||||
|
AssemblyTypeResolutionBehavior.Test ();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
|
@ -92,30 +97,42 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
||||||
}
|
}
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
public class GenericArray<T> { }
|
public class GenericInstantiation<T> { }
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
public class GenericArgument { }
|
public class GenericArgument { }
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
public static void TestGenericArray ()
|
public static void TestGenericInstantiation ()
|
||||||
{
|
{
|
||||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArray`1[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgument]]";
|
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiation`1[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgument]]";
|
||||||
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
public class GenericArrayFullString<T> { }
|
public class GenericInstantiationFullString<T> { }
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
public class GenericArgumentFullString { }
|
public class GenericArgumentFullString { }
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
public static void TestGenericArrayFullString ()
|
public static void TestGenericInstantiationFullString ()
|
||||||
{
|
{
|
||||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArrayFullString`1" +
|
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiationFullString`1["
|
||||||
"[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgumentFullString, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]," +
|
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgumentFullString, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]"
|
||||||
" test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
+ "], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
||||||
|
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
public class GenericInstantiationOverCoreLib<T> { }
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
public static void TestGenericInstantiationOverCoreLib ()
|
||||||
|
{
|
||||||
|
// Note: the argument type should not be assembly-qualified for this test, which is checking that
|
||||||
|
// we can resolve non-assembly-qualified generic argument types from corelib.
|
||||||
|
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiationOverCoreLib`1[[System.String]], test";
|
||||||
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
var typeKept = Type.GetType (reflectionTypeKeptString, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,9 +437,9 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
||||||
[Kept]
|
[Kept]
|
||||||
static void TestGenericTypeWithAnnotations ()
|
static void TestGenericTypeWithAnnotations ()
|
||||||
{
|
{
|
||||||
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_OuterType`1" +
|
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_OuterType`1["
|
||||||
"[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_InnerType, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]," +
|
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_InnerType, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]"
|
||||||
" test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
+ "], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
|
||||||
Type.GetType (reflectionTypeKeptString);
|
Type.GetType (reflectionTypeKeptString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -475,9 +492,75 @@ namespace Mono.Linker.Tests.Cases.Reflection
|
||||||
[Kept]
|
[Kept]
|
||||||
static void TestEscapedTypeName ()
|
static void TestEscapedTypeName ()
|
||||||
{
|
{
|
||||||
var typeKept = Type.GetType ("Library.Not\\+Nested, library");
|
var typeKept = Type.GetType ("Library.Not\\+Nested, EscapedTypeNames");
|
||||||
typeKept = Type.GetType ("Library.Not\\+Nested+Nes\\\\ted, library");
|
typeKept = Type.GetType ("Library.Not\\+Nested+Nes\\\\ted, EscapedTypeNames");
|
||||||
typeKept = Type.GetType ("Library.Not\\+Nested+Nes/ted, library");
|
typeKept = Type.GetType ("Library.Not\\+Nested+Nes/ted, EscapedTypeNames");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
class AssemblyTypeResolutionBehavior
|
||||||
|
{
|
||||||
|
[Kept]
|
||||||
|
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
|
static void TestRequireTypeInSameAssemblyAsGetType () {
|
||||||
|
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.Dependencies.TypeDefinedInSameAssemblyAsGetType");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
|
static void TestRequireTypeInSameAssemblyAsCallToRequireType () {
|
||||||
|
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+TypeDefinedInSameAssemblyAsCallToRequireType");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
|
static void TestRequireTypeWithNonAssemblyQualifiedGenericArguments () {
|
||||||
|
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1[[System.Int32]], test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
|
static void TestRequireTypeWithNonAssemblyQualifiedArrayType () {
|
||||||
|
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
|
||||||
|
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+ArrayElementGenericArgumentType]"
|
||||||
|
+ "][], test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
|
static void TestRequireTypeWithNonAssemblyQualifiedPointerType () {
|
||||||
|
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
|
||||||
|
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+PointerElementGenericArgumentType]"
|
||||||
|
+ "]*, test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
|
||||||
|
static void TestRequireTypeWithNonAssemblyQualifiedByRefType () {
|
||||||
|
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
|
||||||
|
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+ByRefElementGenericArgumentType]"
|
||||||
|
+ "]&, test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Kept]
|
||||||
|
public static void Test () {
|
||||||
|
TestRequireTypeInSameAssemblyAsGetType ();
|
||||||
|
TestRequireTypeInSameAssemblyAsCallToRequireType ();
|
||||||
|
TestRequireTypeWithNonAssemblyQualifiedGenericArguments ();
|
||||||
|
TestRequireTypeWithNonAssemblyQualifiedArrayType ();
|
||||||
|
TestRequireTypeWithNonAssemblyQualifiedPointerType ();
|
||||||
|
TestRequireTypeWithNonAssemblyQualifiedByRefType ();
|
||||||
|
}
|
||||||
|
|
||||||
|
class TypeDefinedInSameAssemblyAsCallToRequireType {}
|
||||||
|
|
||||||
|
class Generic<T> {}
|
||||||
|
|
||||||
|
class ArrayElementGenericArgumentType {}
|
||||||
|
|
||||||
|
class PointerElementGenericArgumentType {}
|
||||||
|
|
||||||
|
class ByRefElementGenericArgumentType {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@ using Mono.Cecil;
|
||||||
using Mono.Cecil.Cil;
|
using Mono.Cecil.Cil;
|
||||||
using Mono.Linker;
|
using Mono.Linker;
|
||||||
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
using Mono.Linker.Tests.Cases.Expectations.Assertions;
|
||||||
|
using Mono.Linker.Tests.Cases.Expectations.Helpers;
|
||||||
using Mono.Linker.Tests.Cases.Expectations.Metadata;
|
using Mono.Linker.Tests.Cases.Expectations.Metadata;
|
||||||
using Mono.Linker.Tests.Extensions;
|
using Mono.Linker.Tests.Extensions;
|
||||||
using Mono.Linker.Tests.TestCasesRunner.ILVerification;
|
using Mono.Linker.Tests.TestCasesRunner.ILVerification;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue