Skip to content

Commit c7708c4

Browse files
committed
Refactor extracting cell data from a notebook
This simplifies the notebook-based go to definition
1 parent cd1a508 commit c7708c4

File tree

2 files changed

+38
-40
lines changed

2 files changed

+38
-40
lines changed

pylsp/python_lsp.py

+19-40
Original file line numberDiff line numberDiff line change
@@ -600,55 +600,34 @@ def m_text_document__code_lens(self, textDocument=None, **_kwargs):
600600
def m_text_document__completion(self, textDocument=None, position=None, **_kwargs):
601601
return self.completions(textDocument['uri'], position)
602602

603-
def _cell_document__definition(self, cellDocument=None, position=None, **_kwargs):
604-
# First, we create a temp TextDocument to send to the hook that represents the whole notebook
605-
# contents.
603+
def _cell_document__definition(self, cellDocument, position=None, **_kwargs):
606604
workspace = self._match_uri_to_workspace(cellDocument.notebook_uri)
607605
notebookDocument = workspace.get_maybe_document(cellDocument.notebook_uri)
608606
if notebookDocument is None:
609607
raise ValueError("Invalid notebook document")
610608

611-
# cell_list helps us map the diagnostics back to the correct cell later.
612-
cell_list: List[Dict[str, Any]] = []
613-
614-
offset = 0
615-
total_source = ""
616-
for cell in notebookDocument.cells:
617-
cell_uri = cell['document']
618-
cell_document = workspace.get_cell_document(cell_uri)
619-
620-
num_lines = cell_document.line_count
621-
622-
data = {
623-
'uri': cell_uri,
624-
'line_start': offset,
625-
'line_end': offset + num_lines - 1,
626-
'source': cell_document.source
627-
}
628-
629-
if position is not None and cell_uri == cellDocument.uri:
630-
position['line'] += offset
609+
cell_data = notebookDocument.cell_data(notebookDocument)
631610

632-
cell_list.append(data)
633-
if offset == 0:
634-
total_source = cell_document.source
635-
else:
636-
total_source += ("\n" + cell_document.source)
611+
# Concatenate all cells to be a single temporary document
612+
total_source = '\n'.join(cell.source for cell in cell_data.values())
613+
with workspace.temp_document(total_source) as temp_uri:
614+
# update position to be the position in the temp document
615+
if position is not None:
616+
position += cell_data[cellDocument.uri]['line_start']
637617

638-
offset += num_lines
618+
definitions = self.definitions(temp_uri, position)
639619

640-
with workspace.temp_document(total_source) as random_uri:
641-
definitions = self.definitions(random_uri, position)
620+
# Translate temp_uri locations to cell document locations
642621
for definition in definitions:
643-
if random_uri == definition['uri']:
644-
# Find the cell the start is in
645-
for cell in cell_list:
646-
# TODO: perhaps it is more correct to check definition['range']['end']['line'] <= cell['line_end'], but
647-
# that would mess up if a definition was split over cells
648-
if cell['line_start'] <= definition['range']['start']['line'] <= cell['line_end']:
649-
definition['uri'] = cell['uri']
650-
definition['range']['start']['line'] -= cell['line_start']
651-
definition['range']['end']['line'] -= cell['line_start']
622+
if definition['uri'] == temp_uri:
623+
# Find the cell the start line is in and adjust the uri and line numbers
624+
for cell_uri, data in cell_data.items():
625+
if data['line_start'] <= definition['range']['start']['line'] <= data['line_end']:
626+
definition['uri'] = cell_uri
627+
definition['range']['start']['line'] -= data['line_start']
628+
definition['range']['end']['line'] -= data['line_start']
629+
break
630+
652631
return definitions
653632

654633
def m_text_document__definition(self, textDocument=None, position=None, **_kwargs):

pylsp/workspace.py

+19
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,25 @@ def add_cells(self, new_cells: List, start: int) -> None:
539539
def remove_cells(self, start: int, delete_count: int) -> None:
540540
del self.cells[start:start+delete_count]
541541

542+
def cell_data(self):
543+
"""Extract current cell data.
544+
545+
Returns a dict (ordered by cell position) where the key is the cell uri and the
546+
value is a dict with line_start, line_end, and source attributes.
547+
"""
548+
cell_data = {}
549+
offset = 0
550+
for cell in self.cells:
551+
cell_uri = cell['document']
552+
cell_document = self.workspace.get_cell_document(cell_uri)
553+
num_lines = cell_document.line_count
554+
cell_data[cell_uri] = {
555+
'line_start': offset,
556+
'line_end': offset + num_lines - 1,
557+
'source': cell_document.source
558+
}
559+
offset += num_lines
560+
return cell_data
542561

543562
class Cell(Document):
544563
"""

0 commit comments

Comments
 (0)