Skip to content

Commit f13a899

Browse files
committed
fix resolving file for type for already decompiled assembly
1 parent 81d2f18 commit f13a899

File tree

1 file changed

+21
-18
lines changed

1 file changed

+21
-18
lines changed

src/SharpIDE.Application/Features/Analysis/WorkspaceServices/DecompileWholeAssemblyToProjectMetadataAsSourceFileProvider.cs

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ internal sealed class DecompileWholeAssemblyToProjectMetadataAsSourceFileProvide
9292
if (_assemblyKeyToProjectInfo.TryGetValue(assemblyKey, out var existingProjectInfo))
9393
{
9494
// The assembly has already been decompiled. Find the document for the requested type.
95-
var primaryFilePath = GetPrimaryFilePath(existingProjectInfo.TempDirectory, topLevelNamedType);
95+
var primaryFilePath = GetPrimaryFilePath(existingProjectInfo.TempDirectory, topLevelNamedType, assemblyKey.Mvid, Path.GetFileNameWithoutExtension(assemblyKey.FilePath));
9696

9797
if (_generatedFilenameToInformation.TryGetValue(primaryFilePath, out var existingDocInfo))
9898
{
@@ -431,21 +431,25 @@ private static (ProjectInfo projectInfo, DocumentId primaryDocumentId, IReadOnly
431431
// Read the assembly name and version from the actual resolved PE (after ref->impl and type-forward resolution),
432432
// not from the symbol in the source compilation which may point to a reference assembly.
433433
AssemblyIdentity? resolvedIdentity = null;
434-
if (portableExecutableReference.GetMetadata() is AssemblyMetadata assemblyMetadata)
434+
if (portableExecutableReference.GetMetadata() is not AssemblyMetadata assemblyMetadata)
435435
{
436-
// The manifest module (first) contains the assembly definition with name and version.
437-
var manifestModule = assemblyMetadata.GetModules().FirstOrDefault();
438-
if (manifestModule is not null)
439-
{
440-
var reader = manifestModule.GetMetadataReader();
441-
var asmDef = reader.GetAssemblyDefinition();
442-
var name = reader.GetString(asmDef.Name);
443-
resolvedIdentity = new AssemblyIdentity(name, asmDef.Version);
444-
}
436+
throw new InvalidOperationException("PE metadata reference must be assembly metadata.");
437+
}
438+
439+
// The manifest module (first) contains the assembly definition with name and version.
440+
var manifestModule = assemblyMetadata.GetModules().FirstOrDefault();
441+
if (manifestModule is not null)
442+
{
443+
var reader = manifestModule.GetMetadataReader();
444+
var asmDef = reader.GetAssemblyDefinition();
445+
var name = reader.GetString(asmDef.Name);
446+
resolvedIdentity = new AssemblyIdentity(name, asmDef.Version);
445447
}
448+
446449
resolvedIdentity ??= topLevelNamedType.ContainingAssembly.Identity;
447450

448451
var assemblyNameForMetadataAsSourceProjectName = resolvedIdentity.Name;
452+
var mvid = assemblyMetadata.GetMvid();
449453
var assemblyVersion = resolvedIdentity.Version;
450454

451455
var compilationOptions = services.GetRequiredLanguageService<ICompilationFactoryService>(fileInfo.LanguageName)
@@ -457,7 +461,7 @@ private static (ProjectInfo projectInfo, DocumentId primaryDocumentId, IReadOnly
457461

458462
// Track which document is the primary one for the requested type.
459463
DocumentId? primaryDocumentId = null;
460-
var primaryRelativePath = GetRelativePathForType(topLevelNamedType);
464+
var primaryRelativePath = GetRelativePathForType(topLevelNamedType, mvid, assemblyNameForMetadataAsSourceProjectName);
461465

462466
if (decompiledFiles is not null && decompiledFiles.Count > 0)
463467
{
@@ -538,22 +542,21 @@ private static (ProjectInfo projectInfo, DocumentId primaryDocumentId, IReadOnly
538542
/// <summary>
539543
/// Computes the expected relative path for a type, matching <see cref="WholeAssemblyDecompiler"/>'s naming logic.
540544
/// </summary>
541-
private static string GetRelativePathForType(INamedTypeSymbol topLevelNamedType)
545+
private static string GetRelativePathForType(INamedTypeSymbol topLevelNamedType, Guid mvid, string assemblyName)
542546
{
543547
var fileName = WholeAssemblyDecompiler.CleanUpFileName(topLevelNamedType.Name, ".cs");
544548
var ns = topLevelNamedType.ContainingNamespace?.ToDisplayString() ?? string.Empty;
545-
if (string.IsNullOrEmpty(ns))
546-
return fileName;
549+
if (string.IsNullOrEmpty(ns)) return fileName;
547550

548551
var dir = WholeAssemblyDecompiler.CleanUpDirectoryName(ns);
549-
return Path.Combine(dir, fileName);
552+
return Path.Combine("decompiled", assemblyName, mvid.ToString(), dir, fileName);
550553
}
551554

552555
/// <summary>
553556
/// Gets the absolute path for the primary file of a type within the assembly's temp directory.
554557
/// </summary>
555-
private static string GetPrimaryFilePath(string tempDirectory, INamedTypeSymbol topLevelNamedType)
556-
=> Path.Combine(tempDirectory, GetRelativePathForType(topLevelNamedType));
558+
private static string GetPrimaryFilePath(string tempDirectory, INamedTypeSymbol topLevelNamedType, Guid mvid, string assemblyName)
559+
=> Path.Combine(tempDirectory, GetRelativePathForType(topLevelNamedType, mvid, assemblyName));
557560

558561
private (PortableExecutableReference? metadataReference, string? assemblyLocation, bool isReferenceAssembly) GetReferenceInfo(Compilation compilation, ISymbol symbolToFind)
559562
{

0 commit comments

Comments
 (0)