From f0b0687631789f54bd24466baf40325dbfa6d458 Mon Sep 17 00:00:00 2001 From: SilverFox Date: Fri, 6 Dec 2019 20:07:42 +0800 Subject: [PATCH] Follow type forward in AnalyzerScope Fix #1845 --- ILSpy/Analyzers/AnalyzerScope.cs | 58 +++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/ILSpy/Analyzers/AnalyzerScope.cs b/ILSpy/Analyzers/AnalyzerScope.cs index 6a6e27344..7e6c6c901 100644 --- a/ILSpy/Analyzers/AnalyzerScope.cs +++ b/ILSpy/Analyzers/AnalyzerScope.cs @@ -134,24 +134,39 @@ namespace ICSharpCode.ILSpy.Analyzers if (typeScope.TypeParameterCount > 0) reflectionTypeScopeName += "`" + typeScope.TypeParameterCount; - foreach (var assembly in AssemblyList.GetAssemblies()) { - ct.ThrowIfCancellationRequested(); - bool found = false; - var module = assembly.GetPEFileOrNull(); - if (module == null || !module.IsAssembly) - continue; - var resolver = assembly.GetAssemblyResolver(); - foreach (var reference in module.AssemblyReferences) { - using (LoadedAssembly.DisableAssemblyLoad()) { - if (resolver.Resolve(reference) == self) { - found = true; - break; + var toWalkFiles = new Stack(); + var checkedFiles = new HashSet(); + + toWalkFiles.Push(self); + checkedFiles.Add(self); + + do { + PEFile curFile = toWalkFiles.Pop(); + foreach (var assembly in AssemblyList.GetAssemblies()) { + ct.ThrowIfCancellationRequested(); + bool found = false; + var module = assembly.GetPEFileOrNull(); + if (module == null || !module.IsAssembly) + continue; + if (checkedFiles.Contains(module)) + continue; + var resolver = assembly.GetAssemblyResolver(); + foreach (var reference in module.AssemblyReferences) { + using (LoadedAssembly.DisableAssemblyLoad()) { + if (resolver.Resolve(reference) == curFile) { + found = true; + break; + } } } + if (found && checkedFiles.Add(module)) { + if (ModuleReferencesScopeType(module.Metadata, reflectionTypeScopeName, typeScope.Namespace)) + yield return module; + if (ModuleForwardsScopeType(module.Metadata, reflectionTypeScopeName, typeScope.Namespace)) + toWalkFiles.Push(module); + } } - if (found && ModuleReferencesScopeType(module.Metadata, reflectionTypeScopeName, typeScope.Namespace)) - yield return module; - } + } while (toWalkFiles.Count > 0); } IEnumerable GetModuleAndAnyFriends(ITypeDefinition typeScope, CancellationToken ct) @@ -198,6 +213,19 @@ namespace ICSharpCode.ILSpy.Analyzers } return hasRef; } + + bool ModuleForwardsScopeType(MetadataReader metadata, string typeScopeName, string typeScopeNamespace) + { + bool hasForward = false; + foreach (var h in metadata.ExportedTypes) { + var exportedType = metadata.GetExportedType(h); + if (exportedType.IsForwarder && metadata.StringComparer.Equals(exportedType.Name, typeScopeName) && metadata.StringComparer.Equals(exportedType.Namespace, typeScopeNamespace)) { + hasForward = true; + break; + } + } + return hasForward; + } #endregion } }