From: Andy Gocke Date: Fri, 30 Jul 2021 20:20:57 +0000 (-0700) Subject: Add RequiresAssemblyFiles attribute (#56196) X-Git-Tag: accepted/tizen/unified/20220110.054933~744 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=45005830255a78caab66cef1757dcb77536f4c0d;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Add RequiresAssemblyFiles attribute (#56196) This PR annotates every API doc'd as having different behavior in single-file publishing with RequiresAssemblyFiles. Some APIs might be special-cased by the analyzer to produce special messages, but RAF is useful for visual inspection of the APIs. Module.Name and .FullyQualifiedName were also unannotated. --- diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index 6f34f7d..0914c0c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -77,11 +77,13 @@ namespace System.Reflection.Emit throw new NotSupportedException(SR.NotSupported_DynamicAssembly); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream GetFile(string name) { throw new NotSupportedException(SR.NotSupported_DynamicAssembly); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { throw new NotSupportedException(SR.NotSupported_DynamicAssembly); @@ -104,7 +106,7 @@ namespace System.Reflection.Emit public override string Location => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); [RequiresUnreferencedCode("Types might be removed")] diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs index c1c243b..230bb06 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -706,6 +706,7 @@ namespace System.Reflection.Emit return GetType(parameters, baseType); } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName => _moduleData._moduleName; [RequiresUnreferencedCode("Trimming changes metadata tokens")] @@ -785,6 +786,7 @@ namespace System.Reflection.Emit public override string ScopeName => InternalModule.ScopeName; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name => InternalModule.Name; public override Assembly Assembly => _assemblyBuilder; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index cb7bd41..5a5fd3e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -83,7 +83,7 @@ namespace System.Reflection return null; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase { get @@ -372,6 +372,7 @@ namespace System.Reflection // Returns the file in the File table of the manifest that matches the // given name. (Name should not include path.) + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream? GetFile(string name) { if (Location.Length == 0) @@ -389,6 +390,7 @@ namespace System.Reflection FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false); } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { if (Location.Length == 0) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index a85a222..a5aad80 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -441,6 +441,7 @@ namespace System.Reflection return retType; } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] internal string GetFullyQualifiedName() { string? fullyQualifiedName = null; @@ -449,9 +450,10 @@ namespace System.Reflection return fullyQualifiedName!; } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName => GetFullyQualifiedName(); - [RequiresUnreferencedCode("Types might be removed")] + [RequiresUnreferencedCode("Types might be removed")] public override Type[] GetTypes() { return GetTypes(this); @@ -518,6 +520,7 @@ namespace System.Reflection } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name { get diff --git a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs index cd420c9..e5ce14b 100644 --- a/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs +++ b/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/LicFileLicenseProvider.cs @@ -3,6 +3,7 @@ using System.ComponentModel.Design; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; @@ -40,6 +41,10 @@ namespace System.ComponentModel /// /// Gets a license for the instance of the component and determines if it is valid. /// + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles", + Justification = "Only used for when Location is non-empty")] + [UnconditionalSuppressMessage("SingleFile", "IL3000:RequiresAssemblyFiles", + Justification = "Location is checked for empty")] public override License? GetLicense(LicenseContext context, Type type, object? instance, bool allowExceptions) { LicFileLicense? lic = null; @@ -69,30 +74,33 @@ namespace System.ComponentModel } } - if (modulePath == null) + if (type.Assembly.Location.Length != 0) { - modulePath = type.Module.FullyQualifiedName; - } + if (modulePath == null) + { + modulePath = type.Module.FullyQualifiedName; + } - string? moduleDir = Path.GetDirectoryName(modulePath); - string licenseFile = moduleDir + "\\" + type.FullName + ".lic"; + string? moduleDir = Path.GetDirectoryName(modulePath); + string licenseFile = moduleDir + "\\" + type.FullName + ".lic"; - Debug.WriteLine($"Looking for license in: {licenseFile}"); - if (File.Exists(licenseFile)) - { - Stream licStream = new FileStream(licenseFile, FileMode.Open, FileAccess.Read, FileShare.Read); - StreamReader sr = new StreamReader(licStream); - string? s = sr.ReadLine(); - sr.Close(); - if (IsKeyValid(s, type)) + Debug.WriteLine($"Looking for license in: {licenseFile}"); + if (File.Exists(licenseFile)) { - lic = new LicFileLicense(this, GetKey(type)); + Stream licStream = new FileStream(licenseFile, FileMode.Open, FileAccess.Read, FileShare.Read); + StreamReader sr = new StreamReader(licStream); + string? s = sr.ReadLine(); + sr.Close(); + if (IsKeyValid(s, type)) + { + lic = new LicFileLicense(this, GetKey(type)); + } } - } - if (lic != null) - { - context!.SetSavedLicenseKey(type, lic.LicenseKey); + if (lic != null) + { + context!.SetSavedLicenseKey(type, lic.LicenseKey); + } } } } diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs index a92612c..747815c 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs +++ b/src/libraries/System.Configuration.ConfigurationManager/src/System/Configuration/ClientConfigPaths.cs @@ -31,6 +31,8 @@ namespace System.Configuration [UnconditionalSuppressMessage("SingleFile", "IL3000: Avoid accessing Assembly file path when publishing as a single file", Justification = "Code handles single file case")] + [UnconditionalSuppressMessage("SingleFile", "IL3002: RequiresAssemblyFiles on Module.Name", + Justification = "Code handles single file case")] private ClientConfigPaths(string exePath, bool includeUserConfig) { _includesUserConfig = includeUserConfig; @@ -222,6 +224,8 @@ namespace System.Configuration // The evidence we use, in priority order, is Strong Name, Url and Exe Path. If one of // these is found, we compute a SHA1 hash of it and return a suffix based on that. // If none is found, we return null. + [UnconditionalSuppressMessage("SingleFile", "IL3002: RequiresAssemblyFiles on Module.Name", + Justification = "Code handles single file case")] private static string GetTypeAndHashSuffix(string exePath, bool isSingleFile) { Assembly assembly = Assembly.GetEntryAssembly(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs index 5b5035b..3612e75 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -81,7 +81,9 @@ namespace System.Reflection [RequiresUnreferencedCode("Types might be removed")] public virtual Type[] GetForwardedTypes() { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + internal const string ThrowingMessageInRAF = "This member throws an exception for assemblies embedded in a single-file app"; + + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual string? CodeBase => throw NotImplemented.ByDesign; public virtual MethodInfo? EntryPoint => throw NotImplemented.ByDesign; public virtual string? FullName => throw NotImplemented.ByDesign; @@ -116,7 +118,7 @@ namespace System.Reflection public virtual object[] GetCustomAttributes(bool inherit) { throw NotImplemented.ByDesign; } public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual string EscapedCodeBase => AssemblyName.EscapeCodeBase(CodeBase); [RequiresUnreferencedCode("Assembly.CreateInstance is not supported with trimming. Use Type.GetType instead.")] @@ -153,9 +155,11 @@ namespace System.Reflection public virtual Assembly GetSatelliteAssembly(CultureInfo culture) { throw NotImplemented.ByDesign; } public virtual Assembly GetSatelliteAssembly(CultureInfo culture, Version? version) { throw NotImplemented.ByDesign; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream? GetFile(string name) { throw NotImplemented.ByDesign; } - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream[] GetFiles() => GetFiles(getResourceModules: false); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public virtual FileStream[] GetFiles(bool getResourceModules) { throw NotImplemented.ByDesign; } public virtual void GetObjectData(SerializationInfo info, StreamingContext context) { throw NotImplemented.ByDesign; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index dc77c94..631b6ea 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -8,7 +8,7 @@ namespace System.Reflection.Emit { public sealed partial class AssemblyBuilder : Assembly { - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); public override string Location => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); public override MethodInfo? EntryPoint => null; @@ -18,9 +18,11 @@ namespace System.Reflection.Emit public override Type[] GetExportedTypes() => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream GetFile(string name) => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs index 4fe3b9a..fc762fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs @@ -13,7 +13,11 @@ namespace System.Reflection protected Module() { } public virtual Assembly Assembly => throw NotImplemented.ByDesign; + + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public virtual string FullyQualifiedName => throw NotImplemented.ByDesign; + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public virtual string Name => throw NotImplemented.ByDesign; public virtual int MDStreamVersion => throw NotImplemented.ByDesign; diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs index c1f11fc..0c34b67 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Delegation/DelegatingModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.Context.Delegation { @@ -22,6 +23,11 @@ namespace System.Reflection.Context.Delegation get { return UnderlyingModule.Assembly; } } + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public override string FullyQualifiedName { get { return UnderlyingModule.FullyQualifiedName; } @@ -42,6 +48,9 @@ namespace System.Reflection.Context.Delegation get { return UnderlyingModule.ModuleVersionId; } } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public override string Name { get { return UnderlyingModule.Name; } diff --git a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs index e823c6a..cbbcaa2 100644 --- a/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs +++ b/src/libraries/System.Reflection.Emit/ref/System.Reflection.Emit.cs @@ -29,7 +29,9 @@ namespace System.Reflection.Emit public System.Reflection.Emit.ModuleBuilder? GetDynamicModule(string name) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public override System.Type[] GetExportedTypes() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public override System.IO.FileStream GetFile(string name) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public override System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } public override int GetHashCode() { throw null; } public override System.Reflection.Module[] GetLoadedModules(bool getResourceModules) { throw null; } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs index 976d002..fea1363 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/Ecma/EcmaAssembly.ManifestResources.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection.Metadata; @@ -51,6 +52,8 @@ namespace System.Reflection.TypeLoading.Ecma return resourceNames; } + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on Module.GetFile", + Justification = "ResourceLocation should never be ContainedInAnotherAssembly if embedded in a single-file")] public sealed override Stream? GetManifestResourceStream(string name) { if (name == null) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs index fe92aa5..d141c71 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.Modules.cs @@ -4,6 +4,7 @@ using System.IO; using System.Threading; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Collections.Generic; namespace System.Reflection.TypeLoading @@ -16,6 +17,9 @@ namespace System.Reflection.TypeLoading public sealed override Module? GetModule(string name) => GetRoModule(name); public sealed override Module[] GetModules(bool getResourceModules) => ComputeRoModules(getResourceModules).CloneArray(); +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(ThrowingMessageInRAF)] +#endif public sealed override FileStream? GetFile(string name) { Module? m = GetModule(name); @@ -24,6 +28,9 @@ namespace System.Reflection.TypeLoading return new FileStream(m.FullyQualifiedName, FileMode.Open, FileAccess.Read, FileShare.Read); } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(ThrowingMessageInRAF)] +#endif public sealed override FileStream[] GetFiles(bool getResourceModules) { Module[] m = GetModules(getResourceModules); diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs index 114f581..4d48000 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Assemblies/RoAssembly.cs @@ -40,16 +40,18 @@ namespace System.Reflection.TypeLoading public sealed override string FullName => _lazyFullName ?? (_lazyFullName = GetName().FullName); private volatile string? _lazyFullName; + internal const string ThrowingMessageInRAF = "This member throws an exception for assemblies embedded in a single-file app"; + // Location and codebase public abstract override string Location { get; } #if NET5_0_OR_GREATER [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string CodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); #if NET5_0_OR_GREATER [Obsolete(Obsoletions.CodeBaseMessage, DiagnosticId = Obsoletions.CodeBaseDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] #endif public sealed override string EscapedCodeBase => throw new NotSupportedException(SR.NotSupported_AssemblyCodeBase); diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs index 78f4d92..cba5234 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/Ecma/EcmaModule.GetTypeCore.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics.CodeAnalysis; using System.Reflection.Metadata; namespace System.Reflection.TypeLoading.Ecma @@ -16,6 +17,8 @@ namespace System.Reflection.TypeLoading.Ecma /// If a type is not contained or forwarded from the assembly, this method returns null (does not throw.) /// This supports the "throwOnError: false" behavior of Module.GetType(string, bool). /// + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on FullyQualifiedName", + Justification = "FullyQualifiedName is only used for exception message")] protected sealed override RoDefinitionType? GetTypeCoreNoCache(ReadOnlySpan ns, ReadOnlySpan name, out Exception? e) { MetadataReader reader = Reader; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs index e9727f2..4ddd442 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Runtime.Serialization; @@ -15,7 +16,7 @@ namespace System.Reflection.TypeLoading { private readonly string _fullyQualifiedName; - internal const string FullyQualifiedNameForModulesLoadedFromByteArrays = ""; + internal const string FullyQualifiedNameForModulesLoadedFromByteArrays = ""; internal RoModule(string fullyQualifiedName) : base() @@ -30,11 +31,19 @@ namespace System.Reflection.TypeLoading public sealed override Assembly Assembly => GetRoAssembly(); internal abstract RoAssembly GetRoAssembly(); + internal const string UnknownStringMessageInRAF = "Returns for modules with no file path"; + +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public sealed override string FullyQualifiedName => _fullyQualifiedName; public abstract override int MDStreamVersion { get; } public abstract override int MetadataToken { get; } public abstract override Guid ModuleVersionId { get; } +#if NET5_0_OR_GREATER + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] +#endif public sealed override string Name { get diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs index 9bff8ab..7e2adb5 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Modules/RoResourceModule.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; namespace System.Reflection.TypeLoading { @@ -30,6 +31,9 @@ namespace System.Reflection.TypeLoading public sealed override int MDStreamVersion => throw new InvalidOperationException(SR.ResourceOnlyModule); public sealed override int MetadataToken => 0x00000000; public sealed override Guid ModuleVersionId => throw new InvalidOperationException(SR.ResourceOnlyModule); + + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles on Name", + Justification = "https://github.com/dotnet/runtime/issues/56519")] public sealed override string ScopeName => Name; public sealed override void GetPEKind(out PortableExecutableKinds peKind, out ImageFileMachine machine) { diff --git a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs index 578d04f..569cc33 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Module/MultiModuleTests.cs @@ -234,8 +234,8 @@ namespace System.Reflection.Tests Assert.Equal(m, m1); Assert.Equal(a, m.Assembly); - Assert.Equal("", m.FullyQualifiedName); - Assert.Equal("", m.Name); + Assert.Equal("", m.FullyQualifiedName); + Assert.Equal("", m.Name); Assert.Equal("Joe.netmodule", m.ScopeName); Assert.Equal(TestData.s_JoeNetModuleMvid, m.ModuleVersionId); } diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index a94b40b..380e0a2 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -11060,13 +11060,13 @@ namespace System.Reflection { protected Assembly() { } [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual string? CodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } public virtual System.Collections.Generic.IEnumerable DefinedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual System.Reflection.MethodInfo? EntryPoint { get { throw null; } } [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual string EscapedCodeBase { get { throw null; } } public virtual System.Collections.Generic.IEnumerable ExportedTypes { [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] get { throw null; } } public virtual string? FullName { get { throw null; } } @@ -11100,9 +11100,11 @@ namespace System.Reflection public static System.Reflection.Assembly GetExecutingAssembly() { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public virtual System.Type[] GetExportedTypes() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream? GetFile(string name) { throw null; } - [System.Diagnostics.CodeAnalysis.RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream[] GetFiles() { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("This member throws an exception for assemblies embedded in a single-file app")] public virtual System.IO.FileStream[] GetFiles(bool getResourceModules) { throw null; } [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Types might be removed")] public virtual System.Type[] GetForwardedTypes() { throw null; } @@ -11867,11 +11869,13 @@ namespace System.Reflection protected Module() { } public virtual System.Reflection.Assembly Assembly { get { throw null; } } public virtual System.Collections.Generic.IEnumerable CustomAttributes { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("Returns for modules with no file path")] public virtual string FullyQualifiedName { get { throw null; } } public virtual int MDStreamVersion { get { throw null; } } public virtual int MetadataToken { get { throw null; } } public System.ModuleHandle ModuleHandle { get { throw null; } } public virtual System.Guid ModuleVersionId { get { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresAssemblyFilesAttribute("Returns for modules with no file path")] public virtual string Name { get { throw null; } } public virtual string ScopeName { get { throw null; } } public override bool Equals(object? o) { throw null; } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs index 86ba437..427767a 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/ModuleBuilder.Mono.cs @@ -106,6 +106,7 @@ namespace System.Reflection.Emit set_wrappers_type(this, type); } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName { get @@ -816,6 +817,7 @@ namespace System.Reflection.Emit get { return assemblyb; } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string Name { get { return name; } @@ -874,7 +876,7 @@ namespace System.Reflection.Emit m = GetRegisteredToken(metadataToken) as MemberInfo; if (m == null) - throw RuntimeModule.resolve_token_exception(Name, metadataToken, error, "MemberInfo"); + throw RuntimeModule.resolve_token_exception(this, metadataToken, error, "MemberInfo"); else return m; } diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs index d5fa9e4..95aed37 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -74,7 +74,7 @@ namespace System.Reflection public override bool ReflectionOnly => false; - [RequiresAssemblyFiles("The code will throw for assemblies embedded in a single-file app")] + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase { get @@ -410,6 +410,7 @@ namespace System.Reflection return res; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream? GetFile(string name) { if (name == null) @@ -430,6 +431,7 @@ namespace System.Reflection return null; } + [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override FileStream[] GetFiles(bool getResourceModules) { if (Location.Length == 0) diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs index 692d7ff..9b92b12 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -56,6 +56,7 @@ namespace System.Reflection get { return assembly; } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override // Note: we do not ask for PathDiscovery because no path is returned here. @@ -94,6 +95,7 @@ namespace System.Reflection } } + [RequiresAssemblyFiles(UnknownStringMessageInRAF)] public override string FullyQualifiedName { @@ -232,7 +234,7 @@ namespace System.Reflection IntPtr handle = ResolveFieldToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "Field"); + throw resolve_token_exception(module, metadataToken, error, "Field"); else return FieldInfo.GetFieldFromHandle(new RuntimeFieldHandle(handle)); } @@ -251,7 +253,7 @@ namespace System.Reflection MemberInfo m = ResolveMemberToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (m == null) - throw resolve_token_exception(module.Name, metadataToken, error, "MemberInfo"); + throw resolve_token_exception(module, metadataToken, error, "MemberInfo"); else return m; } @@ -270,7 +272,7 @@ namespace System.Reflection IntPtr handle = ResolveMethodToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "MethodBase"); + throw resolve_token_exception(module, metadataToken, error, "MethodBase"); else return RuntimeMethodInfo.GetMethodFromHandleNoGenericCheck(new RuntimeMethodHandle(handle)); } @@ -289,7 +291,7 @@ namespace System.Reflection string s = ResolveStringToken(monoModule, metadataToken, out error); if (s == null) - throw resolve_token_exception(module.Name, metadataToken, error, "string"); + throw resolve_token_exception(module, metadataToken, error, "string"); else return s; } @@ -308,7 +310,7 @@ namespace System.Reflection IntPtr handle = ResolveTypeToken(monoModule, metadataToken, ptrs_from_types(genericTypeArguments), ptrs_from_types(genericMethodArguments), out error); if (handle == IntPtr.Zero) - throw resolve_token_exception(module.Name, metadataToken, error, "Type"); + throw resolve_token_exception(module, metadataToken, error, "Type"); else return Type.GetTypeFromHandle(new RuntimeTypeHandle(handle)); } @@ -327,7 +329,7 @@ namespace System.Reflection byte[] res = ResolveSignature(monoModule, metadataToken, out error); if (res == null) - throw resolve_token_exception(module.Name, metadataToken, error, "signature"); + throw resolve_token_exception(module, metadataToken, error, "signature"); else return res; } @@ -364,6 +366,11 @@ namespace System.Reflection return new Guid(guid); } + [UnconditionalSuppressMessage("SingleFile", "IL3002:RequiresAssemblyFiles", + Justification = "Module Name is used only for diagnostic reporting message")] + internal static Exception resolve_token_exception(Module module, int metadataToken, ResolveTokenError error, string tokenType) + => resolve_token_exception(module.Name, metadataToken, error, tokenType); + internal static Exception resolve_token_exception(string name, int metadataToken, ResolveTokenError error, string tokenType) { if (error == ResolveTokenError.OutOfRange)