Browse Source

#nullable enable for UniversalAssemblyResolver

pull/2423/head
Daniel Grunwald 4 years ago
parent
commit
7f36cc3e50
  1. 3
      ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
  2. 91
      ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs
  3. 11
      ICSharpCode.Decompiler/Util/NullAttributes.cs
  4. 1
      ILSpy.AddIn/ILSpy.AddIn.csproj

3
ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
#nullable enable
using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
@ -81,7 +82,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -81,7 +82,7 @@ namespace ICSharpCode.Decompiler.Metadata
/// For .NET Core framework references, the WholeProjectDecompiler will omit the
/// assembly reference if the runtimePack is already included as an SDK.
/// </summary>
public virtual bool IsSharedAssembly(IAssemblyReference reference, out string? runtimePack)
public virtual bool IsSharedAssembly(IAssemblyReference reference, [NotNullWhen(true)] out string? runtimePack)
{
runtimePack = null;
return false;

91
ICSharpCode.Decompiler/Metadata/UniversalAssemblyResolver.cs

@ -16,8 +16,11 @@ @@ -16,8 +16,11 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
@ -64,13 +67,13 @@ namespace ICSharpCode.Decompiler.Metadata @@ -64,13 +67,13 @@ namespace ICSharpCode.Decompiler.Metadata
readonly bool throwOnError;
readonly PEStreamOptions streamOptions;
readonly MetadataReaderOptions metadataOptions;
readonly string mainAssemblyFileName;
readonly string baseDirectory;
readonly List<string> directories = new List<string>();
readonly string? mainAssemblyFileName;
readonly string? baseDirectory;
readonly List<string?> directories = new List<string?>();
static readonly List<string> gac_paths = GetGacPaths();
static readonly DecompilerRuntime decompilerRuntime;
public void AddSearchDirectory(string directory)
public void AddSearchDirectory(string? directory)
{
directories.Add(directory);
if (dotNetCorePathFinder.IsValueCreated)
@ -79,7 +82,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -79,7 +82,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public void RemoveSearchDirectory(string directory)
public void RemoveSearchDirectory(string? directory)
{
directories.Remove(directory);
if (dotNetCorePathFinder.IsValueCreated)
@ -88,7 +91,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -88,7 +91,7 @@ namespace ICSharpCode.Decompiler.Metadata
}
}
public string[] GetSearchDirectories()
public string?[] GetSearchDirectories()
{
return directories.ToArray();
}
@ -121,8 +124,8 @@ namespace ICSharpCode.Decompiler.Metadata @@ -121,8 +124,8 @@ namespace ICSharpCode.Decompiler.Metadata
/// If omitted, falling back to "Microsoft.NETCore.App" and this is ignored in case of classic .NET</param>
/// <param name="streamOptions">Options used for the <see cref="PEReader"/>.</param>
/// <param name="metadataOptions">Options used for the <see cref="MetadataReader"/>.</param>
public UniversalAssemblyResolver(string mainAssemblyFileName, bool throwOnError, string targetFramework,
string runtimePack = null, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
public UniversalAssemblyResolver(string? mainAssemblyFileName, bool throwOnError, string? targetFramework,
string? runtimePack = null, PEStreamOptions streamOptions = PEStreamOptions.Default, MetadataReaderOptions metadataOptions = MetadataReaderOptions.Default)
{
this.mainAssemblyFileName = mainAssemblyFileName;
this.throwOnError = throwOnError;
@ -162,7 +165,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -162,7 +165,7 @@ namespace ICSharpCode.Decompiler.Metadata
break;
}
Version version = null;
Version? version = null;
for (int i = 1; i < tokens.Length; i++)
{
@ -191,20 +194,20 @@ namespace ICSharpCode.Decompiler.Metadata @@ -191,20 +194,20 @@ namespace ICSharpCode.Decompiler.Metadata
}
#if !VSADDIN
public PEFile Resolve(IAssemblyReference name)
public PEFile? Resolve(IAssemblyReference name)
{
var file = FindAssemblyFile(name);
return CreatePEFileFromFileName(file, ex => new ResolutionException(name, file, ex));
}
public PEFile ResolveModule(PEFile mainModule, string moduleName)
public PEFile? ResolveModule(PEFile mainModule, string moduleName)
{
string baseDirectory = Path.GetDirectoryName(mainModule.FileName);
string moduleFileName = Path.Combine(baseDirectory, moduleName);
return CreatePEFileFromFileName(moduleFileName, ex => new ResolutionException(mainModule.FileName, moduleName, moduleFileName, ex));
}
private PEFile CreatePEFileFromFileName(string fileName, Func<Exception?, Exception> makeException)
private PEFile? CreatePEFileFromFileName(string? fileName, Func<Exception?, Exception> makeException)
{
if (fileName == null)
{
@ -231,30 +234,30 @@ namespace ICSharpCode.Decompiler.Metadata @@ -231,30 +234,30 @@ namespace ICSharpCode.Decompiler.Metadata
return null;
}
public Task<PEFile> ResolveAsync(IAssemblyReference name)
public Task<PEFile?> ResolveAsync(IAssemblyReference name)
{
return Task.Run(() => Resolve(name));
}
public Task<PEFile> ResolveModuleAsync(PEFile mainModule, string moduleName)
public Task<PEFile?> ResolveModuleAsync(PEFile mainModule, string moduleName)
{
return Task.Run(() => ResolveModule(mainModule, moduleName));
}
#endif
public override bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack)
public override bool IsSharedAssembly(IAssemblyReference reference, [NotNullWhen(true)] out string? runtimePack)
{
return dotNetCorePathFinder.Value.TryResolveDotNetCoreShared(reference, out runtimePack) != null;
}
public string FindAssemblyFile(IAssemblyReference name)
public string? FindAssemblyFile(IAssemblyReference name)
{
if (name.IsWindowsRuntime)
{
return FindWindowsMetadataFile(name);
}
string file;
string? file;
switch (targetFrameworkIdentifier)
{
case TargetFrameworkIdentifier.NETCoreApp:
@ -291,14 +294,14 @@ namespace ICSharpCode.Decompiler.Metadata @@ -291,14 +294,14 @@ namespace ICSharpCode.Decompiler.Metadata
return dotNetCorePathFinder;
}
string FindWindowsMetadataFile(IAssemblyReference name)
string? FindWindowsMetadataFile(IAssemblyReference name)
{
// Finding Windows Metadata (winmd) is currently only supported on Windows.
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
return null;
// TODO : Find a way to detect the base directory for the required Windows SDK.
string basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Windows Kits", "10", "References");
string? basePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Windows Kits", "10", "References");
if (!Directory.Exists(basePath))
return FindWindowsMetadataInSystemDirectory(name);
@ -332,7 +335,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -332,7 +335,7 @@ namespace ICSharpCode.Decompiler.Metadata
return file;
}
string FindWindowsMetadataInSystemDirectory(IAssemblyReference name)
string? FindWindowsMetadataInSystemDirectory(IAssemblyReference name)
{
string file = Path.Combine(Environment.SystemDirectory, "WinMetadata", name.Name + ".winmd");
if (File.Exists(file))
@ -343,7 +346,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -343,7 +346,7 @@ namespace ICSharpCode.Decompiler.Metadata
/// <summary>
/// This only works on Windows
/// </summary>
string ResolveSilverlight(IAssemblyReference name, Version version)
string? ResolveSilverlight(IAssemblyReference name, Version? version)
{
string[] targetFrameworkSearchPaths = {
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Microsoft Silverlight"),
@ -362,19 +365,19 @@ namespace ICSharpCode.Decompiler.Metadata @@ -362,19 +365,19 @@ namespace ICSharpCode.Decompiler.Metadata
return null;
}
string FindClosestVersionDirectory(string basePath, Version version)
string FindClosestVersionDirectory(string? basePath, Version? version)
{
string path = null;
string? path = null;
foreach (var folder in new DirectoryInfo(basePath).GetDirectories().Select(d => DotNetCorePathFinder.ConvertToVersion(d.Name))
.Where(v => v.Item1 != null).OrderByDescending(v => v.Item1))
{
if (path == null || folder.Item1 >= version)
if (path == null || version == null || folder.Item1 >= version)
path = folder.Item2;
}
return path ?? version.ToString();
return path ?? version?.ToString() ?? ".";
}
string ResolveInternal(IAssemblyReference name)
string? ResolveInternal(IAssemblyReference name)
{
if (name == null)
throw new ArgumentNullException(nameof(name));
@ -421,11 +424,11 @@ namespace ICSharpCode.Decompiler.Metadata @@ -421,11 +424,11 @@ namespace ICSharpCode.Decompiler.Metadata
}
#region .NET / mono GAC handling
string SearchDirectory(IAssemblyReference name, IEnumerable<string> directories)
string? SearchDirectory(IAssemblyReference name, IEnumerable<string?> directories)
{
foreach (var directory in directories)
{
string file = SearchDirectory(name, directory);
string? file = SearchDirectory(name, directory);
if (file != null)
return file;
}
@ -438,7 +441,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -438,7 +441,7 @@ namespace ICSharpCode.Decompiler.Metadata
return IsZeroOrAllOnes(reference.Version) || reference.IsRetargetable;
}
string SearchDirectory(IAssemblyReference name, string directory)
string? SearchDirectory(IAssemblyReference name, string? directory)
{
var extensions = name.IsWindowsRuntime ? new[] { ".winmd", ".dll" } : new[] { ".dll", ".exe" };
foreach (var extension in extensions)
@ -458,7 +461,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -458,7 +461,7 @@ namespace ICSharpCode.Decompiler.Metadata
return null;
}
static bool IsZeroOrAllOnes(Version version)
static bool IsZeroOrAllOnes(Version? version)
{
return version == null
|| (version.Major == 0 && version.Minor == 0 && version.Build == 0 && version.Revision == 0)
@ -467,7 +470,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -467,7 +470,7 @@ namespace ICSharpCode.Decompiler.Metadata
internal static Version ZeroVersion = new Version(0, 0, 0, 0);
string GetCorlib(IAssemblyReference reference)
string? GetCorlib(IAssemblyReference reference)
{
var version = reference.Version;
var corlib = typeof(object).Assembly.GetName();
@ -481,15 +484,19 @@ namespace ICSharpCode.Decompiler.Metadata @@ -481,15 +484,19 @@ namespace ICSharpCode.Decompiler.Metadata
if (reference.PublicKeyToken == null)
return null;
string path;
string? path;
if (decompilerRuntime == DecompilerRuntime.Mono)
{
path = GetMonoMscorlibBasePath(version);
}
else
else if (version != null)
{
path = GetMscorlibBasePath(version, reference.PublicKeyToken.ToHexString(8));
}
else
{
path = null;
}
if (path == null)
return null;
@ -501,9 +508,9 @@ namespace ICSharpCode.Decompiler.Metadata @@ -501,9 +508,9 @@ namespace ICSharpCode.Decompiler.Metadata
return null;
}
string GetMscorlibBasePath(Version version, string publicKeyToken)
string? GetMscorlibBasePath(Version version, string? publicKeyToken)
{
string GetSubFolderForVersion()
string? GetSubFolderForVersion()
{
switch (version.Major)
{
@ -540,7 +547,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -540,7 +547,7 @@ namespace ICSharpCode.Decompiler.Metadata
Path.Combine(rootPath, "Framework64")
};
string folder = GetSubFolderForVersion();
string? folder = GetSubFolderForVersion();
if (folder != null)
{
@ -558,7 +565,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -558,7 +565,7 @@ namespace ICSharpCode.Decompiler.Metadata
return null;
}
string GetMonoMscorlibBasePath(Version version)
string? GetMonoMscorlibBasePath(Version? version)
{
var path = Directory.GetParent(typeof(object).Module.FullyQualifiedName).Parent.FullName;
if (version.Major == 1)
@ -614,7 +621,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -614,7 +621,7 @@ namespace ICSharpCode.Decompiler.Metadata
continue;
var gac_path = Path.Combine(Path.Combine(Path.Combine(prefix, "lib"), "mono"), "gac");
if (Directory.Exists(gac_path) && !paths.Contains(gac))
if (Directory.Exists(gac_path) && !paths.Contains(gac_path))
paths.Add(gac_path);
}
@ -629,7 +636,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -629,7 +636,7 @@ namespace ICSharpCode.Decompiler.Metadata
"gac");
}
public static string GetAssemblyInGac(IAssemblyReference reference)
public static string? GetAssemblyInGac(IAssemblyReference reference)
{
if (reference.PublicKeyToken == null || reference.PublicKeyToken.Length == 0)
return null;
@ -640,7 +647,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -640,7 +647,7 @@ namespace ICSharpCode.Decompiler.Metadata
return GetAssemblyInNetGac(reference);
}
static string GetAssemblyInMonoGac(IAssemblyReference reference)
static string? GetAssemblyInMonoGac(IAssemblyReference reference)
{
for (int i = 0; i < gac_paths.Count; i++)
{
@ -653,7 +660,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -653,7 +660,7 @@ namespace ICSharpCode.Decompiler.Metadata
return null;
}
static string GetAssemblyInNetGac(IAssemblyReference reference)
static string? GetAssemblyInNetGac(IAssemblyReference reference)
{
var gacs = new[] { "GAC_MSIL", "GAC_32", "GAC_64", "GAC" };
var prefixes = new[] { string.Empty, "v4.0_" };
@ -672,7 +679,7 @@ namespace ICSharpCode.Decompiler.Metadata @@ -672,7 +679,7 @@ namespace ICSharpCode.Decompiler.Metadata
return null;
}
static string GetAssemblyFile(IAssemblyReference reference, string prefix, string gac)
static string GetAssemblyFile(IAssemblyReference reference, string? prefix, string? gac)
{
var gac_folder = new StringBuilder()
.Append(prefix)

11
ICSharpCode.Decompiler/Util/NullAttributes.cs

@ -14,5 +14,16 @@ namespace System.Diagnostics.CodeAnalysis @@ -14,5 +14,16 @@ namespace System.Diagnostics.CodeAnalysis
ParameterName = parameterName;
}
}
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
internal sealed class NotNullWhenAttribute : Attribute
{
public NotNullWhenAttribute(bool returnValue)
{
ReturnValue = returnValue;
}
public bool ReturnValue { get; }
}
}
#endif

1
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -72,6 +72,7 @@ @@ -72,6 +72,7 @@
<Compile Include="..\ICSharpCode.Decompiler\Metadata\LightJson\Serialization\TextScanner.cs" Link="Decompiler\LightJson\Serialization\TextScanner.cs" />
<Compile Include="..\ICSharpCode.Decompiler\Metadata\UniversalAssemblyResolver.cs" Link="UniversalAssemblyResolver.cs" />
<Compile Include="..\ICSharpCode.Decompiler\Util\EmptyList.cs" Link="Decompiler\EmptyList.cs" />
<Compile Include="..\ICSharpCode.Decompiler\Util\NullAttributes.cs" Link="NullAttributes.cs" />
<Compile Include="..\ILSpy\NativeMethods.cs" Link="NativeMethods.cs" />
<Compile Include="Commands\AssemblyReferenceForILSpy.cs" />
<Compile Include="Commands\NuGetReferenceForILSpy.cs" />

Loading…
Cancel
Save