Locate implementations for reference assemblies using the GAC#24291
Locate implementations for reference assemblies using the GAC#24291sharwell merged 4 commits intodotnet:dev15.6.xfrom
Conversation
6e37099 to
c0ea68d
Compare
There was a problem hiding this comment.
I don't think we should be resolving or loading assemblies in devenv process.
There was a problem hiding this comment.
Is there something in .Net, the project system, VS, dtar (etc. etc.) that would be able to do this mapping for us?
There was a problem hiding this comment.
We shouldn't report NFW for load failures.
There was a problem hiding this comment.
❓ I was hoping it would provide insight into cases where Navigate to Decompiled Sources doesn't work properly, in order to prioritize future improvements. In light of this, can you confirm that this edge case should be removed from the telemetry consideration?
|
@tmat What if we change this to only consider assemblies that are already loaded in the IDE process? In other words, remove the fallback call to |
|
@sharwell I don't like this approach at all. Customers will get different behavior based on what's loaded in devenv process and what not. That's totally based on what VS features and extension the user have used prior to triggering Go To Disassembly. This would make the feature work seemingly non-deterministically. |
|
@tmat I tried to replace the current logic with |
|
@tmat replied to my question above with the following:
I implemented the suggested approach, and this should be ready for review again. |
d890379 to
4b1853f
Compare
| var reference = compilation.GetMetadataReference(symbol.ContainingAssembly); | ||
|
|
||
| string assemblyLocation = null; | ||
| var isReferenceAssembly = symbol.ContainingAssembly.GetAttributes().Any(attribute => attribute.AttributeClass.Name == nameof(ReferenceAssemblyAttribute)); |
There was a problem hiding this comment.
ReferenceAssemblyAttribute [](start = 137, length = 26)
We should check for namespace as well.
| var fullAssemblyName = symbol.ContainingAssembly.Identity.GetDisplayName(); | ||
| GlobalAssemblyCache.Instance.ResolvePartialName(fullAssemblyName, out assemblyLocation, preferredCulture: CultureInfo.CurrentCulture); | ||
| } | ||
| catch (Exception e) when (FatalError.ReportWithoutCrashUnlessCanceled(e)) |
There was a problem hiding this comment.
ReportWithoutCrashUnlessCanceled [](start = 53, length = 32)
Nit: the code is not cancellable, calling ReportWithoutCrash is sufficient
| if (assemblyLocation == null) | ||
| { | ||
| var reference = compilation.GetMetadataReference(symbol.ContainingAssembly); | ||
| assemblyLocation = reference.Display; |
There was a problem hiding this comment.
reference.Display [](start = 34, length = 18)
Display is only meant to be used in messages for the user.
To get the path of the assembly use (reference as PortableExecutableReference)?.FilePath and handle case when the result is null.
There was a problem hiding this comment.
handle case when the result is null
What would an appropriate error handling strategy be here?
There was a problem hiding this comment.
I guess we should report that we can't navigate to the symbol.
In reply to: 165761856 [](ancestors = 165761856)
Should also check namespace Refers to: src/EditorFeatures/Core/Implementation/MetadataAsSource/MetadataAsSourceFileService.cs:122 in 4b1853f. [](commit_id = 4b1853f, deletion_comment = False) |
* Check fully-qualified names for SuppressIldasmAttribute and ReferenceAssemblyAttribute * Use correct reference location, or fail decompilation if it's not available
|
@tmat Feedback should be addressed now! 😄 |
|
Requesting reviews from @dotnet/roslyn-compiler for the pragma change Requesting reviews from @dotnet/roslyn-ide for behavior |
|
Approved to merge via https://devdiv.visualstudio.com/DevDiv/_workitems/edit/562652 |
jasonmalinowski
left a comment
There was a problem hiding this comment.
Oops I had some pending questions that I never submitted the review on. I approve of the change, treat these as "Jason wants to learn something new" questions.
| <Compile Include="..\..\Compilers\Shared\GlobalAssemblyCacheHelpers\ClrGlobalAssemblyCache.cs" Link="Shared\GlobalAssemblyCacheHelpers\ClrGlobalAssemblyCache.cs" /> | ||
| <Compile Include="..\..\Compilers\Shared\GlobalAssemblyCacheHelpers\FusionAssemblyIdentity.cs" Link="Shared\GlobalAssemblyCacheHelpers\FusionAssemblyIdentity.cs" /> | ||
| <Compile Include="..\..\Compilers\Shared\GlobalAssemblyCacheHelpers\GlobalAssemblyCache.cs" Link="Shared\GlobalAssemblyCacheHelpers\GlobalAssemblyCache.cs" /> | ||
| <Compile Include="..\..\Compilers\Shared\GlobalAssemblyCacheHelpers\MonoGlobalAssemblyCache.cs" Link="Shared\GlobalAssemblyCacheHelpers\MonoGlobalAssemblyCache.cs" /> |
There was a problem hiding this comment.
Hmm, how does this work with cross-plat? There's some runtime sniffing to use the right one at runtime?
| throw new ArgumentException(Scripting.ScriptingResources.InvalidCharactersInAssemblyName, nameof(name)); | ||
|
|
||
| #elif WORKSPACE_DESKTOP | ||
| #elif WORKSPACE_DESKTOP || EDITOR_FEATURES |
There was a problem hiding this comment.
@tmat How do we eventually detangle this linked file mess?
This pull request partially implements the "locate the runtime assembly" feature described in #24349, specifically for cases where the metadata reference resolves to a reference assembly (i.e. an assembly which does not contain IL for method bodies). Reference assemblies do not produce meaningful results when decompiled, and currently all references to the .NET Framework assemblies fall into this category. For common assemblies already located in the GAC, including the .NET Framework assemblies, this pull request allows the Navigate to Decompiled Sources feature to provide meaningful results.
Fixes #24185 (other related limitations will become separate bugs)
Customer scenario
A user attempts to use the Navigate to Decompiled Sources feature to navigate to a member defined as part of the .NET Framework. The feature does not work as expected, because the decompiled source file shows the code for a reference assembly, which does not have any contents in the bodies of members.
Bugs this fixes
Fixes #24185
Workarounds, if any
None.
Risk
Low. This only impacts the Navigate to Decompiled Sources feature, which is disabled by default and only exposed as an experimental option in the Advanced page of C# settings.
Performance impact
This code is only in effect on the code paths where it is required.
Is this a regression from a previous update?
No.
Root cause analysis
Known limitation of a new feature.
How was the bug found?
Known limitation of a new feature.
Test documentation updated?
Yes.