Browse Source

`#enable nullable` for a couple of files.

Includes some fixes for potential NullReferenceExceptions.
pull/2308/head
Daniel Grunwald 4 years ago
parent
commit
281586de1f
  1. 1
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
  2. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 36
      ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs
  4. 30
      ICSharpCode.Decompiler/Metadata/Dom.cs
  5. 8
      ICSharpCode.Decompiler/Metadata/PEFile.cs
  6. 9
      ICSharpCode.Decompiler/Util/LazyInit.cs
  7. 18
      ICSharpCode.Decompiler/Util/NullAttributes.cs
  8. 1
      ILSpy.AddIn/ILSpy.AddIn.csproj
  9. 2
      ILSpy/ILSpy.csproj
  10. 76
      ILSpy/LoadedAssembly.cs
  11. 30
      ILSpy/LoadedPackage.cs

1
ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs

@ -134,6 +134,7 @@ namespace LocalFunctions
} }
} }
} }
Console.WriteLine(t2);
return StaticInvokeAsFunc(MixedLocalFunction2Delegate<T1>) + StaticInvokeAsFunc(MixedLocalFunction2Delegate<T2>) + StaticInvokeAsFunc(StaticMethod1<decimal>) + StaticInvokeAsFunc(StaticMethod1<int>) + StaticInvokeAsFunc(NonStaticMethod3) + StaticInvokeAsFunc(StaticMethod5<T1>) + new Func<object, int>(StaticMethod4<object>)(null) + StaticInvokeAsFunc2<object>(StaticMethod4<object>) + new Func<Func<object, int>, int>(StaticInvokeAsFunc2<object>)(StaticMethod4<object>); return StaticInvokeAsFunc(MixedLocalFunction2Delegate<T1>) + StaticInvokeAsFunc(MixedLocalFunction2Delegate<T2>) + StaticInvokeAsFunc(StaticMethod1<decimal>) + StaticInvokeAsFunc(StaticMethod1<int>) + StaticInvokeAsFunc(NonStaticMethod3) + StaticInvokeAsFunc(StaticMethod5<T1>) + new Func<object, int>(StaticMethod4<object>)(null) + StaticInvokeAsFunc2<object>(StaticMethod4<object>) + new Func<Func<object, int>, int>(StaticInvokeAsFunc2<object>)(StaticMethod4<object>);
int NonStaticMethod3() int NonStaticMethod3()
{ {

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -421,6 +421,7 @@
<Compile Include="Util\GraphVizGraph.cs" /> <Compile Include="Util\GraphVizGraph.cs" />
<Compile Include="Util\KeyComparer.cs" /> <Compile Include="Util\KeyComparer.cs" />
<Compile Include="Util\LongDict.cs" /> <Compile Include="Util\LongDict.cs" />
<Compile Include="Util\NullAttributes.cs" />
<Compile Include="Util\ResourcesFile.cs" /> <Compile Include="Util\ResourcesFile.cs" />
<Compile Include="Util\ResXResourceWriter.cs" /> <Compile Include="Util\ResXResourceWriter.cs" />
<Compile Include="Util\UnicodeNewline.cs" /> <Compile Include="Util\UnicodeNewline.cs" />

36
ICSharpCode.Decompiler/Metadata/AssemblyReferences.cs

@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
#nullable enable
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -36,7 +38,7 @@ namespace ICSharpCode.Decompiler.Metadata
{ {
} }
public AssemblyResolutionException(IAssemblyReference reference, Exception innerException) public AssemblyResolutionException(IAssemblyReference reference, Exception? innerException)
: base($"Failed to resolve assembly: '{reference}'", innerException) : base($"Failed to resolve assembly: '{reference}'", innerException)
{ {
this.Reference = reference; this.Reference = reference;
@ -46,10 +48,10 @@ namespace ICSharpCode.Decompiler.Metadata
public interface IAssemblyResolver public interface IAssemblyResolver
{ {
#if !VSADDIN #if !VSADDIN
PEFile Resolve(IAssemblyReference reference); PEFile? Resolve(IAssemblyReference reference);
PEFile ResolveModule(PEFile mainModule, string moduleName); PEFile? ResolveModule(PEFile mainModule, string moduleName);
Task<PEFile> ResolveAsync(IAssemblyReference reference); Task<PEFile?> ResolveAsync(IAssemblyReference reference);
Task<PEFile> ResolveModuleAsync(PEFile mainModule, string moduleName); Task<PEFile?> ResolveModuleAsync(PEFile mainModule, string moduleName);
#endif #endif
} }
@ -68,7 +70,7 @@ namespace ICSharpCode.Decompiler.Metadata
/// For .NET Core framework references, the WholeProjectDecompiler will omit the /// For .NET Core framework references, the WholeProjectDecompiler will omit the
/// assembly reference if the runtimePack is already included as an SDK. /// assembly reference if the runtimePack is already included as an SDK.
/// </summary> /// </summary>
public virtual bool IsSharedAssembly(IAssemblyReference reference, out string runtimePack) public virtual bool IsSharedAssembly(IAssemblyReference reference, out string? runtimePack)
{ {
runtimePack = null; runtimePack = null;
return false; return false;
@ -79,9 +81,9 @@ namespace ICSharpCode.Decompiler.Metadata
{ {
string Name { get; } string Name { get; }
string FullName { get; } string FullName { get; }
Version Version { get; } Version? Version { get; }
string Culture { get; } string? Culture { get; }
byte[] PublicKeyToken { get; } byte[]? PublicKeyToken { get; }
bool IsWindowsRuntime { get; } bool IsWindowsRuntime { get; }
bool IsRetargetable { get; } bool IsRetargetable { get; }
@ -89,9 +91,9 @@ namespace ICSharpCode.Decompiler.Metadata
public class AssemblyNameReference : IAssemblyReference public class AssemblyNameReference : IAssemblyReference
{ {
string fullName; string? fullName;
public string Name { get; private set; } public string Name { get; private set; } = string.Empty;
public string FullName { public string FullName {
get { get {
@ -132,11 +134,11 @@ namespace ICSharpCode.Decompiler.Metadata
} }
} }
public Version Version { get; private set; } public Version? Version { get; private set; }
public string Culture { get; private set; } public string? Culture { get; private set; }
public byte[] PublicKeyToken { get; private set; } public byte[]? PublicKeyToken { get; private set; }
public bool IsWindowsRuntime { get; private set; } public bool IsWindowsRuntime { get; private set; }
@ -234,11 +236,11 @@ namespace ICSharpCode.Decompiler.Metadata
} }
} }
public Version Version => entry.Version; public Version? Version => entry.Version;
public string Culture => Metadata.GetString(entry.Culture); public string Culture => Metadata.GetString(entry.Culture);
byte[] IAssemblyReference.PublicKeyToken => GetPublicKeyToken(); byte[]? IAssemblyReference.PublicKeyToken => GetPublicKeyToken();
public byte[] GetPublicKeyToken() public byte[]? GetPublicKeyToken()
{ {
if (entry.PublicKeyOrToken.IsNil) if (entry.PublicKeyOrToken.IsNil)
return null; return null;

30
ICSharpCode.Decompiler/Metadata/Dom.cs

@ -1,4 +1,6 @@
using System; #nullable enable
using System;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
@ -32,7 +34,7 @@ namespace ICSharpCode.Decompiler.Metadata
public virtual ResourceType ResourceType => ResourceType.Embedded; public virtual ResourceType ResourceType => ResourceType.Embedded;
public virtual ManifestResourceAttributes Attributes => ManifestResourceAttributes.Public; public virtual ManifestResourceAttributes Attributes => ManifestResourceAttributes.Public;
public abstract string Name { get; } public abstract string Name { get; }
public abstract Stream TryOpenStream(); public abstract Stream? TryOpenStream();
} }
public class ByteArrayResource : Resource public class ByteArrayResource : Resource
@ -98,12 +100,16 @@ namespace ICSharpCode.Decompiler.Metadata
return ResourceType.Linked; return ResourceType.Linked;
} }
public override unsafe Stream TryOpenStream() public override unsafe Stream? TryOpenStream()
{ {
if (ResourceType != ResourceType.Embedded) if (ResourceType != ResourceType.Embedded)
return null; return null;
var headers = Module.Reader.PEHeaders; var headers = Module.Reader.PEHeaders;
if (headers.CorHeader == null)
return null;
var resources = headers.CorHeader.ResourcesDirectory; var resources = headers.CorHeader.ResourcesDirectory;
if (resources.RelativeVirtualAddress == 0)
return null;
var sectionData = Module.Reader.GetSectionData(resources.RelativeVirtualAddress); var sectionData = Module.Reader.GetSectionData(resources.RelativeVirtualAddress);
if (sectionData.Length == 0) if (sectionData.Length == 0)
throw new BadImageFormatException("RVA could not be found in any section!"); throw new BadImageFormatException("RVA could not be found in any section!");
@ -231,7 +237,7 @@ namespace ICSharpCode.Decompiler.Metadata
public class GenericContext public class GenericContext
{ {
readonly MetadataReader metadata; readonly MetadataReader? metadata;
readonly TypeDefinitionHandle declaringType; readonly TypeDefinitionHandle declaringType;
readonly MethodDefinitionHandle method; readonly MethodDefinitionHandle method;
@ -268,7 +274,7 @@ namespace ICSharpCode.Decompiler.Metadata
public string GetGenericTypeParameterName(int index) public string GetGenericTypeParameterName(int index)
{ {
GenericParameterHandle genericParameter = GetGenericTypeParameterHandleOrNull(index); GenericParameterHandle genericParameter = GetGenericTypeParameterHandleOrNull(index);
if (genericParameter.IsNil) if (genericParameter.IsNil || metadata == null)
return index.ToString(); return index.ToString();
return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name); return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name);
} }
@ -276,23 +282,27 @@ namespace ICSharpCode.Decompiler.Metadata
public string GetGenericMethodTypeParameterName(int index) public string GetGenericMethodTypeParameterName(int index)
{ {
GenericParameterHandle genericParameter = GetGenericMethodTypeParameterHandleOrNull(index); GenericParameterHandle genericParameter = GetGenericMethodTypeParameterHandleOrNull(index);
if (genericParameter.IsNil) if (genericParameter.IsNil || metadata == null)
return index.ToString(); return index.ToString();
return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name); return metadata.GetString(metadata.GetGenericParameter(genericParameter).Name);
} }
public GenericParameterHandle GetGenericTypeParameterHandleOrNull(int index) public GenericParameterHandle GetGenericTypeParameterHandleOrNull(int index)
{ {
GenericParameterHandleCollection genericParameters; if (declaringType.IsNil || index < 0 || metadata == null)
if (declaringType.IsNil || index < 0 || index >= (genericParameters = metadata.GetTypeDefinition(declaringType).GetGenericParameters()).Count) return MetadataTokens.GenericParameterHandle(0);
var genericParameters = metadata.GetTypeDefinition(declaringType).GetGenericParameters();
if (index >= genericParameters.Count)
return MetadataTokens.GenericParameterHandle(0); return MetadataTokens.GenericParameterHandle(0);
return genericParameters[index]; return genericParameters[index];
} }
public GenericParameterHandle GetGenericMethodTypeParameterHandleOrNull(int index) public GenericParameterHandle GetGenericMethodTypeParameterHandleOrNull(int index)
{ {
GenericParameterHandleCollection genericParameters; if (method.IsNil || index < 0 || metadata == null)
if (method.IsNil || index < 0 || index >= (genericParameters = metadata.GetMethodDefinition(method).GetGenericParameters()).Count) return MetadataTokens.GenericParameterHandle(0);
var genericParameters = metadata.GetMethodDefinition(method).GetGenericParameters();
if (index >= genericParameters.Count)
return MetadataTokens.GenericParameterHandle(0); return MetadataTokens.GenericParameterHandle(0);
return genericParameters[index]; return genericParameters[index];
} }

8
ICSharpCode.Decompiler/Metadata/PEFile.cs

@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
@ -121,7 +123,7 @@ namespace ICSharpCode.Decompiler.Metadata
Reader.Dispose(); Reader.Dispose();
} }
Dictionary<TopLevelTypeName, TypeDefinitionHandle> typeLookup; Dictionary<TopLevelTypeName, TypeDefinitionHandle>? typeLookup;
/// <summary> /// <summary>
/// Finds the top-level-type with the specified name. /// Finds the top-level-type with the specified name.
@ -152,7 +154,7 @@ namespace ICSharpCode.Decompiler.Metadata
return default; return default;
} }
Dictionary<FullTypeName, ExportedTypeHandle> typeForwarderLookup; Dictionary<FullTypeName, ExportedTypeHandle>? typeForwarderLookup;
/// <summary> /// <summary>
/// Finds the type forwarder with the specified name. /// Finds the type forwarder with the specified name.
@ -176,7 +178,7 @@ namespace ICSharpCode.Decompiler.Metadata
return default; return default;
} }
MethodSemanticsLookup methodSemanticsLookup; MethodSemanticsLookup? methodSemanticsLookup;
internal MethodSemanticsLookup MethodSemanticsLookup { internal MethodSemanticsLookup MethodSemanticsLookup {
get { get {

9
ICSharpCode.Decompiler/Util/LazyInit.cs

@ -16,13 +16,15 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
#nullable enable
using System.Diagnostics.CodeAnalysis;
using System.Threading; using System.Threading;
namespace ICSharpCode.Decompiler.Util namespace ICSharpCode.Decompiler.Util
{ {
public static class LazyInit public static class LazyInit
{ {
public static T VolatileRead<T>(ref T location) where T : class public static T VolatileRead<T>(ref T location) where T : class?
{ {
return Volatile.Read(ref location); return Volatile.Read(ref location);
} }
@ -32,9 +34,10 @@ namespace ICSharpCode.Decompiler.Util
/// - If target is null: stores newValue in target and returns newValue. /// - If target is null: stores newValue in target and returns newValue.
/// - If target is not null: returns target. /// - If target is not null: returns target.
/// </summary> /// </summary>
public static T GetOrSet<T>(ref T target, T newValue) where T : class [return: NotNullIfNotNull("newValue")]
public static T? GetOrSet<T>(ref T? target, T? newValue) where T : class
{ {
T oldValue = Interlocked.CompareExchange(ref target, newValue, null); T? oldValue = Interlocked.CompareExchange(ref target, newValue, null);
return oldValue ?? newValue; return oldValue ?? newValue;
} }
} }

18
ICSharpCode.Decompiler/Util/NullAttributes.cs

@ -0,0 +1,18 @@
#if !NETCORE
#nullable enable
namespace System.Diagnostics.CodeAnalysis
{
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)]
internal sealed class NotNullIfNotNullAttribute : Attribute
{
public string ParameterName { get; }
public NotNullIfNotNullAttribute(string parameterName)
{
ParameterName = parameterName;
}
}
}
#endif

1
ILSpy.AddIn/ILSpy.AddIn.csproj

@ -14,6 +14,7 @@
<Description>ILSpy</Description> <Description>ILSpy</Description>
<Version>1.7.1.0</Version> <Version>1.7.1.0</Version>
<FileVersion>1.7.1.0</FileVersion> <FileVersion>1.7.1.0</FileVersion>
<LangVersion>9.0</LangVersion>
<EnableDefaultItems>False</EnableDefaultItems> <EnableDefaultItems>False</EnableDefaultItems>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>

2
ILSpy/ILSpy.csproj

@ -4,7 +4,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>net472</TargetFramework> <TargetFramework>net472</TargetFramework>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<LangVersion>8.0</LangVersion> <LangVersion>9.0</LangVersion>
<GenerateAssemblyInfo>False</GenerateAssemblyInfo> <GenerateAssemblyInfo>False</GenerateAssemblyInfo>
<AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>false</AutoGenerateBindingRedirects>
<GenerateSupportedRuntime>false</GenerateSupportedRuntime> <GenerateSupportedRuntime>false</GenerateSupportedRuntime>

76
ILSpy/LoadedAssembly.cs

@ -35,6 +35,8 @@ using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.Options; using ICSharpCode.ILSpy.Options;
#nullable enable
namespace ICSharpCode.ILSpy namespace ICSharpCode.ILSpy
{ {
/// <summary> /// <summary>
@ -61,9 +63,9 @@ namespace ICSharpCode.ILSpy
public sealed class LoadResult public sealed class LoadResult
{ {
public PEFile PEFile { get; } public PEFile? PEFile { get; }
public Exception PEFileLoadException { get; } public Exception? PEFileLoadException { get; }
public LoadedPackage Package { get; } public LoadedPackage? Package { get; }
public LoadResult(PEFile peFile) public LoadResult(PEFile peFile)
{ {
@ -80,12 +82,12 @@ namespace ICSharpCode.ILSpy
readonly AssemblyList assemblyList; readonly AssemblyList assemblyList;
readonly string fileName; readonly string fileName;
readonly string shortName; readonly string shortName;
readonly IAssemblyResolver providedAssemblyResolver; readonly IAssemblyResolver? providedAssemblyResolver;
public LoadedAssembly ParentBundle { get; } public LoadedAssembly? ParentBundle { get; }
public LoadedAssembly(AssemblyList assemblyList, string fileName, public LoadedAssembly(AssemblyList assemblyList, string fileName,
Task<Stream> stream = null, IAssemblyResolver assemblyResolver = null, string pdbFileName = null) Task<Stream?>? stream = null, IAssemblyResolver? assemblyResolver = null, string? pdbFileName = null)
{ {
this.assemblyList = assemblyList ?? throw new ArgumentNullException(nameof(assemblyList)); this.assemblyList = assemblyList ?? throw new ArgumentNullException(nameof(assemblyList));
this.fileName = fileName ?? throw new ArgumentNullException(nameof(fileName)); this.fileName = fileName ?? throw new ArgumentNullException(nameof(fileName));
@ -96,7 +98,7 @@ namespace ICSharpCode.ILSpy
this.shortName = Path.GetFileNameWithoutExtension(fileName); this.shortName = Path.GetFileNameWithoutExtension(fileName);
} }
public LoadedAssembly(LoadedAssembly bundle, string fileName, Task<Stream> stream, IAssemblyResolver assemblyResolver = null) public LoadedAssembly(LoadedAssembly bundle, string fileName, Task<Stream?>? stream, IAssemblyResolver assemblyResolver = null)
: this(bundle.assemblyList, fileName, stream, assemblyResolver) : this(bundle.assemblyList, fileName, stream, assemblyResolver)
{ {
this.ParentBundle = bundle; this.ParentBundle = bundle;
@ -116,7 +118,7 @@ namespace ICSharpCode.ILSpy
public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo(); public ReferenceLoadInfo LoadedAssemblyReferencesInfo { get; } = new ReferenceLoadInfo();
IDebugInfoProvider debugInfoProvider; IDebugInfoProvider? debugInfoProvider;
/// <summary> /// <summary>
/// Gets the <see cref="LoadResult"/>. /// Gets the <see cref="LoadResult"/>.
@ -135,14 +137,14 @@ namespace ICSharpCode.ILSpy
if (loadResult.PEFile != null) if (loadResult.PEFile != null)
return loadResult.PEFile; return loadResult.PEFile;
else else
throw loadResult.PEFileLoadException; throw loadResult.PEFileLoadException!;
} }
/// <summary> /// <summary>
/// Gets the <see cref="PEFile"/>. /// Gets the <see cref="PEFile"/>.
/// Returns null in case of load errors. /// Returns null in case of load errors.
/// </summary> /// </summary>
public PEFile GetPEFileOrNull() public PEFile? GetPEFileOrNull()
{ {
try try
{ {
@ -160,7 +162,7 @@ namespace ICSharpCode.ILSpy
/// Gets the <see cref="PEFile"/>. /// Gets the <see cref="PEFile"/>.
/// Returns null in case of load errors. /// Returns null in case of load errors.
/// </summary> /// </summary>
public async Task<PEFile> GetPEFileOrNullAsync() public async Task<PEFile?> GetPEFileOrNullAsync()
{ {
try try
{ {
@ -174,7 +176,7 @@ namespace ICSharpCode.ILSpy
} }
} }
ICompilation typeSystem; ICompilation? typeSystem;
/// <summary> /// <summary>
/// Gets a type system containing all types from this assembly + primitive types from mscorlib. /// Gets a type system containing all types from this assembly + primitive types from mscorlib.
@ -183,7 +185,7 @@ namespace ICSharpCode.ILSpy
/// <remarks> /// <remarks>
/// This is an uncached type system. /// This is an uncached type system.
/// </remarks> /// </remarks>
public ICompilation GetTypeSystemOrNull() public ICompilation? GetTypeSystemOrNull()
{ {
return LazyInitializer.EnsureInitialized(ref this.typeSystem, () => { return LazyInitializer.EnsureInitialized(ref this.typeSystem, () => {
var module = GetPEFileOrNull(); var module = GetPEFileOrNull();
@ -196,10 +198,10 @@ namespace ICSharpCode.ILSpy
} }
readonly object typeSystemWithOptionsLockObj = new object(); readonly object typeSystemWithOptionsLockObj = new object();
ICompilation typeSystemWithOptions; ICompilation? typeSystemWithOptions;
TypeSystemOptions currentTypeSystemOptions; TypeSystemOptions? currentTypeSystemOptions;
public ICompilation GetTypeSystemOrNull(TypeSystemOptions options) public ICompilation? GetTypeSystemOrNull(TypeSystemOptions options)
{ {
lock (typeSystemWithOptionsLockObj) lock (typeSystemWithOptionsLockObj)
{ {
@ -225,9 +227,9 @@ namespace ICSharpCode.ILSpy
get { get {
if (IsLoaded && !HasLoadError) if (IsLoaded && !HasLoadError)
{ {
PEFile module = GetPEFileOrNull(); PEFile? module = GetPEFileOrNull();
var metadata = module?.Metadata; var metadata = module?.Metadata;
string versionOrInfo = null; string? versionOrInfo = null;
if (metadata != null) if (metadata != null)
{ {
if (metadata.IsAssembly) if (metadata.IsAssembly)
@ -278,14 +280,14 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Gets the PDB file name or null, if no PDB was found or it's embedded. /// Gets the PDB file name or null, if no PDB was found or it's embedded.
/// </summary> /// </summary>
public string PdbFileName { get; private set; } public string? PdbFileName { get; private set; }
async Task<LoadResult> LoadAsync(Task<Stream> streamTask) async Task<LoadResult> LoadAsync(Task<Stream?>? streamTask)
{ {
// runs on background thread // runs on background thread
if (streamTask != null) var stream = streamTask != null ? await streamTask.ConfigureAwait(false) : null;
if (stream != null)
{ {
var stream = await streamTask;
// Read the module from a precrafted stream // Read the module from a precrafted stream
if (!stream.CanSeek) if (!stream.CanSeek)
{ {
@ -357,7 +359,7 @@ namespace ICSharpCode.ILSpy
return new LoadResult(module); return new LoadResult(module);
} }
IDebugInfoProvider LoadDebugInfo(PEFile module) IDebugInfoProvider? LoadDebugInfo(PEFile module)
{ {
if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols) if (DecompilerSettingsPanel.CurrentDecompilerSettings.UseDebugSymbols)
{ {
@ -380,7 +382,7 @@ namespace ICSharpCode.ILSpy
return null; return null;
} }
public async Task<IDebugInfoProvider> LoadDebugInfo(string fileName) public async Task<IDebugInfoProvider?> LoadDebugInfo(string fileName)
{ {
this.PdbFileName = fileName; this.PdbFileName = fileName;
var assembly = await GetPEFileAsync().ConfigureAwait(false); var assembly = await GetPEFileAsync().ConfigureAwait(false);
@ -393,7 +395,7 @@ namespace ICSharpCode.ILSpy
readonly LoadedAssembly parent; readonly LoadedAssembly parent;
readonly bool loadOnDemand; readonly bool loadOnDemand;
readonly IAssemblyResolver providedAssemblyResolver; readonly IAssemblyResolver? providedAssemblyResolver;
readonly AssemblyList assemblyList; readonly AssemblyList assemblyList;
readonly LoadedAssembly[] alreadyLoadedAssemblies; readonly LoadedAssembly[] alreadyLoadedAssemblies;
readonly Task<string> tfmTask; readonly Task<string> tfmTask;
@ -416,13 +418,13 @@ namespace ICSharpCode.ILSpy
this.referenceLoadInfo = parent.LoadedAssemblyReferencesInfo; this.referenceLoadInfo = parent.LoadedAssemblyReferencesInfo;
} }
public PEFile Resolve(IAssemblyReference reference) public PEFile? Resolve(IAssemblyReference reference)
{ {
return ResolveAsync(reference).GetAwaiter().GetResult(); return ResolveAsync(reference).GetAwaiter().GetResult();
} }
Dictionary<string, PEFile> asmLookupByFullName; Dictionary<string, PEFile>? asmLookupByFullName;
Dictionary<string, PEFile> asmLookupByShortName; Dictionary<string, PEFile>? asmLookupByShortName;
/// <summary> /// <summary>
/// 0) if we're inside a package, look for filename.dll in parent directories /// 0) if we're inside a package, look for filename.dll in parent directories
@ -436,9 +438,9 @@ namespace ICSharpCode.ILSpy
/// 8) search C:\Windows\Microsoft.NET\Framework64\v4.0.30319 /// 8) search C:\Windows\Microsoft.NET\Framework64\v4.0.30319
/// 9) try to find match by asm name (no tfm/version) in loaded assemblies /// 9) try to find match by asm name (no tfm/version) in loaded assemblies
/// </summary> /// </summary>
public async Task<PEFile> ResolveAsync(IAssemblyReference reference) public async Task<PEFile?> ResolveAsync(IAssemblyReference reference)
{ {
PEFile module; PEFile? module;
// 0) if we're inside a package, look for filename.dll in parent directories // 0) if we're inside a package, look for filename.dll in parent directories
if (providedAssemblyResolver != null) if (providedAssemblyResolver != null)
{ {
@ -527,7 +529,9 @@ namespace ICSharpCode.ILSpy
try try
{ {
var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false); var module = await loaded.GetPEFileOrNullAsync().ConfigureAwait(false);
var reader = module?.Metadata; if (module == null)
continue;
var reader = module.Metadata;
if (reader == null || !reader.IsAssembly) if (reader == null || !reader.IsAssembly)
continue; continue;
var asmDef = reader.GetAssemblyDefinition(); var asmDef = reader.GetAssemblyDefinition();
@ -547,12 +551,12 @@ namespace ICSharpCode.ILSpy
return result; return result;
} }
public PEFile ResolveModule(PEFile mainModule, string moduleName) public PEFile? ResolveModule(PEFile mainModule, string moduleName)
{ {
return ResolveModuleAsync(mainModule, moduleName).GetAwaiter().GetResult(); return ResolveModuleAsync(mainModule, moduleName).GetAwaiter().GetResult();
} }
public async Task<PEFile> ResolveModuleAsync(PEFile mainModule, string moduleName) public async Task<PEFile?> ResolveModuleAsync(PEFile mainModule, string moduleName)
{ {
if (providedAssemblyResolver != null) if (providedAssemblyResolver != null)
{ {
@ -608,7 +612,7 @@ namespace ICSharpCode.ILSpy
private MyUniversalResolver GetUniversalResolver() private MyUniversalResolver GetUniversalResolver()
{ {
return LazyInitializer.EnsureInitialized(ref this.universalResolver, () => new MyUniversalResolver(this)); return LazyInitializer.EnsureInitialized(ref this.universalResolver, () => new MyUniversalResolver(this))!;
} }
public AssemblyReferenceClassifier GetAssemblyReferenceClassifier() public AssemblyReferenceClassifier GetAssemblyReferenceClassifier()
@ -619,7 +623,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Returns the debug info for this assembly. Returns null in case of load errors or no debug info is available. /// Returns the debug info for this assembly. Returns null in case of load errors or no debug info is available.
/// </summary> /// </summary>
public IDebugInfoProvider GetDebugInfoOrNull() public IDebugInfoProvider? GetDebugInfoOrNull()
{ {
if (GetPEFileOrNull() == null) if (GetPEFileOrNull() == null)
return null; return null;
@ -634,7 +638,7 @@ namespace ICSharpCode.ILSpy
} }
} }
MyUniversalResolver universalResolver; MyUniversalResolver? universalResolver;
/// <summary> /// <summary>
/// Wait until the assembly is loaded. /// Wait until the assembly is loaded.

30
ILSpy/LoadedPackage.cs

@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
#nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -45,7 +47,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Gets the LoadedAssembly instance representing this bundle. /// Gets the LoadedAssembly instance representing this bundle.
/// </summary> /// </summary>
internal LoadedAssembly LoadedAssembly { get; set; } internal LoadedAssembly? LoadedAssembly { get; set; }
public PackageKind Kind { get; } public PackageKind Kind { get; }
@ -106,7 +108,7 @@ namespace ICSharpCode.ILSpy
/// <summary> /// <summary>
/// Load a .NET single-file bundle. /// Load a .NET single-file bundle.
/// </summary> /// </summary>
public static LoadedPackage FromBundle(string fileName) public static LoadedPackage? FromBundle(string fileName)
{ {
using var memoryMappedFile = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read); using var memoryMappedFile = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read);
var view = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read); var view = memoryMappedFile.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
@ -144,7 +146,7 @@ namespace ICSharpCode.ILSpy
public override ManifestResourceAttributes Attributes => originalEntry.Attributes; public override ManifestResourceAttributes Attributes => originalEntry.Attributes;
public override string FullName => originalEntry.FullName; public override string FullName => originalEntry.FullName;
public override ResourceType ResourceType => originalEntry.ResourceType; public override ResourceType ResourceType => originalEntry.ResourceType;
public override Stream TryOpenStream() => originalEntry.TryOpenStream(); public override Stream? TryOpenStream() => originalEntry.TryOpenStream();
} }
sealed class ZipFileEntry : PackageEntry sealed class ZipFileEntry : PackageEntry
@ -159,7 +161,7 @@ namespace ICSharpCode.ILSpy
this.Name = entry.FullName; this.Name = entry.FullName;
} }
public override Stream TryOpenStream() public override Stream? TryOpenStream()
{ {
Debug.WriteLine("Decompress " + Name); Debug.WriteLine("Decompress " + Name);
using var archive = ZipFile.OpenRead(zipFile); using var archive = ZipFile.OpenRead(zipFile);
@ -221,9 +223,9 @@ namespace ICSharpCode.ILSpy
public string Name { get; } public string Name { get; }
readonly LoadedPackage package; readonly LoadedPackage package;
readonly PackageFolder parent; readonly PackageFolder? parent;
internal PackageFolder(LoadedPackage package, PackageFolder parent, string name) internal PackageFolder(LoadedPackage package, PackageFolder? parent, string name)
{ {
this.package = package; this.package = package;
this.parent = parent; this.parent = parent;
@ -233,7 +235,7 @@ namespace ICSharpCode.ILSpy
public List<PackageFolder> Folders { get; } = new List<PackageFolder>(); public List<PackageFolder> Folders { get; } = new List<PackageFolder>();
public List<PackageEntry> Entries { get; } = new List<PackageEntry>(); public List<PackageEntry> Entries { get; } = new List<PackageEntry>();
public PEFile Resolve(IAssemblyReference reference) public PEFile? Resolve(IAssemblyReference reference)
{ {
var asm = ResolveFileName(reference.Name + ".dll"); var asm = ResolveFileName(reference.Name + ".dll");
if (asm != null) if (asm != null)
@ -243,7 +245,7 @@ namespace ICSharpCode.ILSpy
return parent?.Resolve(reference); return parent?.Resolve(reference);
} }
public Task<PEFile> ResolveAsync(IAssemblyReference reference) public Task<PEFile?> ResolveAsync(IAssemblyReference reference)
{ {
var asm = ResolveFileName(reference.Name + ".dll"); var asm = ResolveFileName(reference.Name + ".dll");
if (asm != null) if (asm != null)
@ -254,10 +256,10 @@ namespace ICSharpCode.ILSpy
{ {
return parent.ResolveAsync(reference); return parent.ResolveAsync(reference);
} }
return Task.FromResult<PEFile>(null); return Task.FromResult<PEFile?>(null);
} }
public PEFile ResolveModule(PEFile mainModule, string moduleName) public PEFile? ResolveModule(PEFile mainModule, string moduleName)
{ {
var asm = ResolveFileName(moduleName + ".dll"); var asm = ResolveFileName(moduleName + ".dll");
if (asm != null) if (asm != null)
@ -267,7 +269,7 @@ namespace ICSharpCode.ILSpy
return parent?.ResolveModule(mainModule, moduleName); return parent?.ResolveModule(mainModule, moduleName);
} }
public Task<PEFile> ResolveModuleAsync(PEFile mainModule, string moduleName) public Task<PEFile?> ResolveModuleAsync(PEFile mainModule, string moduleName)
{ {
var asm = ResolveFileName(moduleName + ".dll"); var asm = ResolveFileName(moduleName + ".dll");
if (asm != null) if (asm != null)
@ -278,12 +280,12 @@ namespace ICSharpCode.ILSpy
{ {
return parent.ResolveModuleAsync(mainModule, moduleName); return parent.ResolveModuleAsync(mainModule, moduleName);
} }
return Task.FromResult<PEFile>(null); return Task.FromResult<PEFile?>(null);
} }
readonly Dictionary<string, LoadedAssembly> assemblies = new Dictionary<string, LoadedAssembly>(StringComparer.OrdinalIgnoreCase); readonly Dictionary<string, LoadedAssembly?> assemblies = new Dictionary<string, LoadedAssembly?>(StringComparer.OrdinalIgnoreCase);
internal LoadedAssembly ResolveFileName(string name) internal LoadedAssembly? ResolveFileName(string name)
{ {
if (package.LoadedAssembly == null) if (package.LoadedAssembly == null)
return null; return null;

Loading…
Cancel
Save