posit-dev / posit-dev/positron
Go to definition: static versus dynamic views
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4.3k
- Forks
- 184
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 206
Description
There are both static and dynamic aspects to "go to definition".
We support static definitions for top-level functions and objects:
foo <- function() {}
foo # F12 jumps to line 1
bar <- 1
bar # F12 jumps to line 4
We could also support dynamic definitions by delegating to View():
-
We can
View()any function defined in the R session. This uses source reference if available and can either jump to the actual location from where the object was sourced, producing a similar effect to the static definition jump, or to a virtual namespace generated by Ark. If the object doesn't have any source references, we generate a virtual document for it, similar to RStudio. This was implemented recently in https://github.com/posit-dev/ark/pull/848. -
We can
View()data frames defined in the R session to open a Data Viewer editor.
From what I can see, "go to definition" in RStudio works like this:
- If a function is statically indexed at top-level, RStudio consistently jumps to the definition. Other top-level variables are not supported in this way.
- If a function is defined in the session but not at top-level, the R function is deparsed and opened as virtual document.
- If a variable is defined in the session, a data view is opened.
So the general idea is that for functions, static definitions have priority over dynamic definitions. For variables, only dynamic views from objects defined in the session are supported.
In Positron things are a little different:
-
We plan to make our LSP independent of the session (https://github.com/posit-dev/positron/issues/2321). When used outside Positron or when a session is shut down, dynamic definitions will not be available at all.
-
We already support top-level variables, and plan to support local variables as well. The idea is to follow general LSP principles and provide definition navigation for variables (https://github.com/posit-dev/positron/issues/8631). The general principle is that static definitions should be consistent with "unknown symbol" diagnostics. If the LSP knows that a variable is defined, it should jump to the most relevant (closest) definition.
Here are some approaches we could take in this context:
-
Use
View()as a fallback only when a static definition is not available. Essentially we'd extend to variables RStudio's existing behaviour for functions, where static definitions have priority over dynamic ones.mtcars # F12 opens a data viewer mtcars <- mtcars mtcars # F12 jumps to line 3 -
Only use static definitions for the "go to definition" feature but provide a "code action" (lightbulb) that maps to
View()when the cursor is on a variable for which we have a dynamic definition. Of course users can still callView()manually, or use the View button in the Variables pane. We could also have a View command that could be bind to a keyboard shortcut.
Although that second option deviates from RStudio, I would weakly favour it because it would make the definition feature work more consistently and its behaviour more predictable? One key thing to note about that fallback View() behaviour, is that the symbol under cursor might not be related at all to the object in memory. If the object in memory was created at an unrelated location, and only happens to have the same name as the symbol under cursor, jumping to it might be more confusing than helpful.
Edit: We could also support both, with View() as fallback being a user setting (turned off by default?). Having the code action is still useful even if we have the View() fallback as it would be an easy way to opt into viewing the dynamic definition when a static one also exists.
Note: This issue is conceptually related to whether we should take into account dynamic objects in diagnostics. I've written about it there: https://github.com/posit-dev/positron/issues/2321#issuecomment-3072885419.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the linked discussions for issues #2321 and #8631 and the Ark pull request #848 context. Compare static definition navigation with dynamic View() behavior for functions and variables. Done should be a documented decision on fallback, code-action, and setting behavior, followed by a scoped implementation plan.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- r
- Domain
- developer-experience, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100