Skip to content

Conversation

@stellarshenson
Copy link

References

Fixes #1096

Based on standalone extension: jupyterlab_jump_to_definition_fix

Jump-to-definition fails when packages are installed in a kernel environment different from the JupyterLab server environment. This is common in multi-environment deployments using nb_conda_kernels or similar setups.

Code changes

Added a kernel-based Jedi fallback mechanism that activates when the LSP server returns no jump targets.

Backend (python_packages/jupyter_lsp/jupyter_lsp/handlers.py):

  • Added IntrospectionCodeHandler class serving GET /lsp/introspection-code
  • Returns Python code template for Jedi-based introspection that executes in kernel context
  • Uses kernel's sys.path for accurate import resolution

Frontend (packages/jupyterlab-lsp/src/features/jump_to.ts):

  • isPythonNotebook() - Detects Python kernels via notebook language metadata
  • _fetchIntrospectionCode() - Retrieves introspection template from server
  • jumpWithKernelJedi() - Executes Jedi in kernel, parses result, opens target file

Fallback flow:

  1. Assemble complete notebook source from all code cells
  2. Compute cursor position (line, column) accounting for cell offsets
  3. Execute Jedi introspection code in kernel via kernel.requestExecute()
  4. Parse JSON result containing file path and line number
  5. Convert absolute path to JupyterLab-relative path
  6. Open document at definition line via documentManager.openOrReveal()

Schema (packages/jupyterlab-lsp/schema/jump_to.json):

  • Added enableKernelFallback boolean setting (default: true)
  • Allows users to disable fallback if undesired

User-facing changes

  • Jump-to-definition now works for packages installed only in the kernel environment
  • New setting "Enable kernel fallback" in LSP settings (enabled by default)
  • Requires jedi package installed in kernel environment for fallback to work

Before: "No jump targets found" when package exists only in kernel env

After: Opens source file at definition line

Backwards-incompatible changes

None. Existing LSP-based behavior is unchanged. Fallback only triggers when LSP returns no targets.

Chores

  • linted (jlpm prettier, flake8, eslint:check - all pass)
  • tested (manual testing with multi-environment setup)
  • documented
  • changelog entry

When LSP returns no jump targets, fall back to using Jedi in the kernel
environment. This enables jump-to-definition for packages installed only
in the kernel environment (not in JupyterLab's environment).

Changes:
- Add IntrospectionCodeHandler backend endpoint at /lsp/introspection-code
- Add jumpWithKernelJedi() method with detailed logging
- Add enableKernelFallback setting (default: true)
- Bump version to 5.2.1
- Fix premature "No jump targets found" notification showing before kernel fallback completes
- Add local development files to .gitignore (Makefile, .claude/, PULL_REQUEST.md)
- Fix line length issues in handlers.py introspection code
- Prettier formatting for jump_to.ts
- Add changelog entry for jupyterlab-lsp 5.2.1
@github-actions
Copy link

Binder 👈 Launch a binder notebook on branch stellarshenson/jupyterlab-lsp/fix/jupyterlab_jump_to_definition_fix

@krassowski
Copy link
Member

Thank you for opening the PR! While I see the benefits of using the kernel to get such information, I think the solution for LSP specifically would be to have a way to pass environment path to the LSP server, otherwise we end up reimplementing the LSP logic for each feature and each language.

@stellarshenson
Copy link
Author

agreed, that was one of the reasons why I built the fix as an extension - to have the capability in the absence of the official support in the jupyterlab-lsp

having kernel-based jump-to-definition is quite critical, as for now project package (cookiecutter based projects) would need to be installed in base to make the jump-to-definition work

@krassowski
Copy link
Member

as for now project package (cookiecutter based projects) would need to be installed in base to make the jump-to-definition work

but it should not be the case; it should be as simple as configuring the LSP server to look in your environment. What we should have in jupyterlab-lsp is a way to automatically pass the path of the kernel environment down to LSP server config.

@stellarshenson
Copy link
Author

stellarshenson commented Nov 26, 2025

I see, so that when LSP launches for the given kernel session - it does make use of the kerne's environment, is that what you meant?

Because I have been finishing another project - to embark more environments to present kernels to Jupyterlab
Project nb_venv_kernels built on top of nb_conda_kernels

It introduces VEnvKernelSpecManager for uv, venv (python) and conda (fallback to CondaKernelSpecManager) as virtual environment accesible to Jupyterlab via ipykernel package.

@stellarshenson
Copy link
Author

I can try figure it out within jupyterlab-lsp architecture to make it, so that kernel's environment would be seen by the language server all along, but that'd take some digging

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

jump to definition doesn't work if code deployed in conda environment other than base

2 participants