-
Notifications
You must be signed in to change notification settings - Fork 30
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RFC: Include "F12 - go to decompiled source" in OmniSharp? #45
Comments
@filipw I don't want to "pollute" the OmniSharp repo with a discussion that might be totally inappropriate, that's why I tagged you here. Would that sort of feature be of value in OmniSharp (and part of its charter), or is that something that is not of interest feature-wise? |
Hi sorry for the delay, I somehow missed it. Yes we absolutely want to bring this feature into OmniSharp - it's been quite heavily asked for. At the moment we only support metadata as source which is very limited. |
ICSharpCode.Decompiler.dll is already included in Roslyn (but not latest, that somehow always takes some time). Please feel free to take inspiration from this repository, we actually would love to have it (F12 experience) part and parcel in OmniSharp! |
I will have a look and come back to you with questions 😀 |
No problem, @siegfriedpammer and I will be watching this space :-) There are additional samples available, such as ilspycmd (https://github.com/icsharpcode/ILSpy/tree/master/ICSharpCode.Decompiler.Console) or even inside Roslyn you will find the integration code that Siegfried provided. |
See https://github.com/dotnet/roslyn/tree/master/src/EditorFeatures/CSharp/DecompiledSource for the Roslyn integration. |
@filipw saw your branch https://github.com/filipw/omnisharp-roslyn/tree/feature/decompile - anything we can help with? |
thanks unfortunately I got side tracked with a lot of other things in OmniSharp which had taken priority 😫 |
Currently, VS is also using a toggle plus that copyright dialog (Yes -> decompile, No -> use good old metadata approach). However, they honor an additional one that you might want to consider given that VSCode is a MS product: https://github.com/dotnet/roslyn/blob/e704ca635bd6de70a0250e34c4567c7a28fa9f6d/src/EditorFeatures/Core/Implementation/MetadataAsSource/MetadataAsSourceFileService.cs#L121-L126 is the check for the SuppressIldasm attribute. The comments on the blog article https://devblogs.microsoft.com/visualstudio/decompilation-of-c-code-made-easy-with-visual-studio/ indicate that people really seem to care about this "be nice" attribute.... (haven't had a too close look at your code, you might already implicitly using that via Roslyn, so don't know) |
@filipw We are approaching Preview 3 of v6 - and would have a few spare cycles to help. |
thanks, the latest code has been moved to the official feature branch (it's currently on top of latest master) https://github.com/OmniSharp/omnisharp-roslyn/tree/feature/decompile |
Did you encounter any problems, snags, things we could do differently to make it easier, any other suggestions? |
i tried a few approaches, but ended up reflection calling into the internal Roslyn services, it's the simplest and this way the behavior appears to be pretty much the same |
@christophwille actually, perhaps you could help here? it tries to look for
|
@siegfriedpammer I think you are better suited to answer this |
Yes, I wrote that code, however I am merely a consumer of another Roslyn API namely In Visual Studio's case we retrieve all known references and use their file locations from I don't know anything about how OmniSharp uses Roslyn, maybe there's some difference in how the |
thanks. What the assembly resolver for ILSpy in Roslyn code does, is this http://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp.EditorFeatures/DecompiledSource/AssemblyResolver.cs,104 So it uses It appears that in VS it only works cause Display is null and it goes through the fallback, but in our case I internalized all that code into OmniSharp (which is not great as there is a lot of copying and a lot of internal reflection, instead of a single top level reflection call) and switched to use |
I am sorry for the confusion, I was referring to the
The problem here is that Maybe @sharwell could step in and provide more information? Would it be acceptable to do an |
|
actually, ofcourse what I wrote is nonsense 😄
this is what I ended up using on the feature branch too https://github.com/OmniSharp/omnisharp-roslyn/blob/feature/decompile/src/OmniSharp.Roslyn.CSharp/Services/Decompilation/AssemblyResolver.cs#L96-L102 |
Filip's PR is here OmniSharp/omnisharp-roslyn#1751 |
@filipw I saw that it was just merged. I assume you will be blogging / tweeting once it ships to end users - please let us know so we can retweet. Thanks. Our extension will continue to exist - for one, we allow decompilation of user-selected assemblies (no project context), secondly it allows us to ship ics.d versions different from Roslyn, thirdly it has a tree UI similar to ILSpy itself. |
It seems to be in 1.21.17 https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp @filipw can you confirm? (how would I go about activating the feature?) |
yes it's released now. To activate it you can do one of 2 things: create a global or local And add the following config:
In the future, we will add a shortcut setting directly into VS Code settings too. @christophwille @siegfriedpammer actually, there is one more issue that you maybe can help with. On Windows everything works as expected, on Mono as well, for "regular" references (nuget packages or external DLLs), however when trying to navigate to BCL types on Mono we get
Is it expected that it would behave like this when the application is running inside a Mono VM? |
That depends on how you create the decompiler type system. It is necessary that all types you try to decompile are located in the main module, that is, the first parameter of the Could you point me to the location were you instantiate the decompiler so I can take a look? Thank you very much! |
thanks a lot - it's here https://github.com/OmniSharp/omnisharp-roslyn/blob/master/src/OmniSharp.Roslyn.CSharp/Services/Decompilation/OmniSharpCSharpDecompiledSourceService.cs#L128 |
I think I would have to debug this in order to get some insight as to why it fails. Is it possible to reproduce this in a Ubuntu VM? I currently do not have access to my MBP. |
I will try to create a repro. So the following code:
prints this on Mono:
In this case the problem is we are in net472 project (omnisharp) but working on a net core 3.1 project. I am trying to decompile something from This is caused by this special handling of ref assemblies. When I get rid of this code https://github.com/OmniSharp/omnisharp-roslyn/blob/master/src/OmniSharp.Roslyn.CSharp/Services/Decompilation/OmniSharpCSharpDecompiledSourceService.cs#L72-L91 (which, as mentioned, comes from http://sourceroslyn.io/#Microsoft.CodeAnalysis.CSharp.EditorFeatures/DecompiledSource/CSharpDecompiledSourceService.cs,51) then it seems to work fine. Decompilation works then and I see:
Do you know why in VS they have the extra search in GAC? I think we can safely remove it. |
Reference assemblies are useless for a decompiler (as they only contain public metadata and zero implementation). VS usually works with reference assemblies, because these suffice for most IDE features, but the decompiler needs an assembly containing the actual implementation. I don't quite understand: The assembly from the Microsoft.NETCore.App.Ref path contains IL bytes, but the Mono facade does not? |
The mono facade does too, but there is a mismatch of versions (assembly from .NET core 3.1 is newer than in Mono GAC as it only matches on partial name) so this condition is not satisfied https://github.com/icsharpcode/ILSpy/blob/master/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs#L826 When I remove any attempt to handle ref assemblies, at least the ref assemblies gets decompiled. This is of course quite useless, but at least better than the exception. Also - most importantly - that's the same behavior I see in VS anyway - ref assemblies don't work correctly for me in VS2019 and I just see decompiled ref assembly with properties and methods that throw null. This is acceptable for now I'd say. |
This is definitely not helpful and not what I had in mind for the feature, but due to some missing functionality in Visual Studio, that is, answering the question "Which file is loaded at runtime for the given assembly?", the feature will always misbehave in some cases. That question is - of course - very hard to answer, depending the project configuration, etc., so we might never get it to work properly everywhere. The VS debugger team afaik uses the assemblies loaded into the debuggee, so they do not have this problem.
If that "fixes" the problem for OmniSharp on all supported platforms, please go for it. As I said before, the "runtime assembly" question is hard to answer. Sorry, for not being able to provide a good solution to this. ILSpy itself uses a lot of complex code to correctly handle .NET Framework, .NET Core and Portable assemblies and their references. And even with that we might not get it right, but in our case the user still has the possibility to manually add the correct assemblies to the current assembly list. |
Thanks, this is definitely complex, especially when the code targeted and the code running are different runtimes. What I have managed to find out is that the problem in this code that we mirrored from VS, is that it ends up using a Mono specific implementation of some Roslyn GAC proxy (http://sourceroslyn.io/#Microsoft.CodeAnalysis.Scripting/Hosting/Resolvers/MonoGlobalAssemblyCache.cs,fa2b10cde63dabec) that is not in use in VS at all - since, well, it's mono specific. It works in a questionable way - it was built for C# scripting to handle the x-plat semantics there and it for example picks 4.5 facades even when 4.7.2 facades are available too and so on. Then the mismatch causes the not supported exception which makes things even worse. I think we take a step back and remove any attempts to handle ref assemblies for now, and (it appears to me) this would bring it on par with the current IDE VS experience anyway. We can then improve upon this later progressively. |
Are there current plans for the shortcut setting yet? |
it's planned but apparently there need to be some things defined first on how the legal disclaimer is shown and so on |
Ah yes, something along the lines of the dialog that pops up in Visual Studio. |
@christophwille You can try this in our pre-release build https://github.com/OmniSharp/omnisharp-vscode/releases/tag/v1.21.19-beta1 |
That should be easy enough for everyone to find :-) I am closing this issue - if you have further questions (@filipw or @JoeRobich) about specifics of our engine, feature requests or bugs, please use https://github.com/icsharpcode/ILSpy/issues. We are more than happy to help. |
Thank you very much for this feature! I couldn't use VS Code for C# without it. Would it be possible that features like "Find References" would work as expected in decompiled files? E.g. finding references in that decompiled source as well as finding references in my project. |
Visual Studio already integrates the ILSpy decompilation engine as an experimental F12 go to decompiled source. Given how "small" such an integration is, wouldn't that also be of interest in the OmniSharp engine to have that sort of functionality in-box? (ie like this: if package has SourceLink, use that. If not, use our engine).
Maybe we should start a discussion with the https://github.com/OmniSharp/omnisharp-roslyn devs if that is even within their charter.
Our addin hasn't seen and proably won't see much additional activity feature-wise (it started out as a proof that we are actually properly x-plat). Thus having it integrated in the C# feature for VS Code might be way more appropriate.
The text was updated successfully, but these errors were encountered: