Implementing `Navigate -> Declaration` action going to declaration for runtime type instead of the compile-time type while debugging
I'd like to investigate implementing https://youtrack.jetbrains.com/issue/IDEA-86569, i.e., while debugging, the `Navigate -> Declaration` (⌘B) action should go to the declaration for the actual runtime type instead of the compile-time static type.
Could this feature be implemented as a plugin, or must I modify the IntelliJ codebase?
I'd prefer to make this work for all supported languages (e.g., Java, Kotlin, JavaScript, etc.), but, if support is different for different languages, I'll start with Java, unless another one is much easier.
It seems that `Navigate -> Declaration` is implemented by `com.intellij.codeInsight.navigation.actions.GotoDeclarationAction$invoke(…)`, but, when I debugged IntelliJ to track things down, it used a cache of usage-to-declaration mappings.
What IntelliJ IDEA code from the GitHub repo (https://github.com/JetBrains/intellij-community) initially determines the declaration for a usage?
I'll need to implement a `GotoDeclarationHandler` to avoid the existing cached static usage-to-declaration mappings, right?
It seems like I'll need to investigate `com.intellij.debugger.codeinsight.RuntimeTypeEvaluator` to find out the runtime type of an object, correct?
FYI, I haven't previously written any IntelliJ IDEA plugins, or worked with the IntelliJ code base.
Thanks for any help.
Please sign in to leave a comment.
Yes, implementing GotoDeclarationHandler should do the trick.
RuntimeTypeEvaluator should help determing the real expression type, but you'll have to extract the parent expression
I'm getting back to looking into this.
Can you point out an exact line of code, where, for normal circumstances in the java debugger:
1) the declaration for a usage is determined
2) the runtime type of an object is known
Once I know these 2 lines of code, I can backtrack to figure out how to implement the functionality described in the initial post of this thread.
Please let me know if any of this doesn't make sense, and then I'll attempt to clarify.
Thanks.
I'm getting back to looking into this.
Can someone point out an exact line of code, where, for normal circumstances in the java debugger:
1) the declaration for a reference usage is determined
2) the runtime type of an object is known
Once I know these 2 lines of code, I can backtrack to figure out how to implement the functionality described in the initial post of this thread.
Please let me know if any of this doesn't make sense, and then I'll attempt to clarify.
Thanks.
1) the declaration for a reference usage is determined here:
com.intellij.codeInsight.navigation.actions.GotoDeclarationAction#findTargetElementsNoVS
which calls com.intellij.codeInsight.navigation.actions.GotoDeclarationAction#findTargetElementsFromProviders
which goes over implementations of com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler
which you want to implement.
2) RuntimeTypeEvaluator is the closest to what you need right now
Thanks for the info. Will investigate in a bit.
I'm looking into this again. GotoDeclarationAction doesn't seem to be used in the same way by 2020.2 as it was in older versions. I've looked through other code & found places where goto is actually handled now.
I tried putting breakpoints in all the methods of RuntimeTypeEvaluator, but no breakpoints were tripped in my main IDE when I debugged runIde and ran a debugger in the IDE that was being debugged (the secondary IDE). When paused on a breakpoint in the secondary IDE, I saw the correct runtime types for variables in the Variables tab of the Debug tool window, but no breakpoints were tripped in the main IDE, so it looks like RuntimeTypeEvaluator isn't being used to determine the runtime types for variables in the Variables tab of the Debug tool window.
Can you let me know what code is used to determine the runtime type of a variable for display in the Variables tab of the Debug tool window in IDEA 2020.2? If it's different for different languages, then Java would be the best language to know. Preferably the line where the actual determination is made, rather than where it might be retrieved from a cache.
Is the "Symbol API based Go To Declaration" the best code to investigate, or is it better to investigate the code that will run if "Symbol API based Go To Declaration" is not used? My installation uses "Symbol API based Go To Declaration", but I didn't intentionally enable it.
In both cases it boils down to the `com.intellij.codeInsight.navigation.action.GotoDeclarationUtil#findTargetElementsFromProviders(com.intellij.psi.PsiElement, int, com.intellij.openapi.editor.Editor)` which calls `com.intellij.codeInsight.navigation.actions.GotoDeclarationHandler`. Implement it and put a breakpoint in your implementation if you want to investigate how exactly it's called and what happens to the returned result.