posit-dev / posit-dev/positron

Go to definition: static versus dynamic views

Open
#8,632 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area: symbols lang: r
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 call View() 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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.