From 4da44a2398012d957ec7e4fd390a764c035c20a6 Mon Sep 17 00:00:00 2001 From: Lie Ryan Date: Fri, 8 Mar 2024 22:31:59 +1100 Subject: [PATCH] Always create `new_project()` when renaming It seems like there's strange desynchronisation issues between client buffer state and rope's if we reused the project. We'll eventually want to fix this, but for now, this works the least awful. --- pylsp_rope/plugin.py | 7 +++++-- pylsp_rope/project.py | 24 ++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/pylsp_rope/plugin.py b/pylsp_rope/plugin.py index 3a216fd..3d9a3b1 100644 --- a/pylsp_rope/plugin.py +++ b/pylsp_rope/plugin.py @@ -2,6 +2,7 @@ from typing import List, Optional from pylsp import hookimpl, uris +from rope.base import libutils from pylsp.lsp import MessageType from rope.refactor.rename import Rename @@ -11,6 +12,7 @@ get_resource, get_resources, rope_changeset_to_workspace_edit, + new_project, ) @@ -178,8 +180,8 @@ def pylsp_rename( return None logger.info("textDocument/rename: %s %s %s", document, position, new_name) - project = get_project(workspace) - current_document, resource = get_resource(workspace, document.uri) + project = new_project(workspace) # FIXME: we shouldn't have to always keep creating new projects here + document, resource = get_resource(workspace, document.uri, project=project) rename = Rename( project=project, @@ -194,6 +196,7 @@ def pylsp_rename( ) rope_changeset = rename.get_changes(new_name, in_hierarchy=True, docs=True) + logger.debug("Finished rename: %s", rope_changeset.changes) workspace_edit = rope_changeset_to_workspace_edit( workspace, diff --git a/pylsp_rope/project.py b/pylsp_rope/project.py index b9254a1..ba317fb 100644 --- a/pylsp_rope/project.py +++ b/pylsp_rope/project.py @@ -1,3 +1,4 @@ +from __future__ import annotations import logging from functools import lru_cache from typing import List, Dict, Tuple, Optional @@ -24,15 +25,34 @@ @lru_cache(maxsize=None) def get_project(workspace) -> rope.Project: + """Get a cached rope Project or create one if it doesn't exist yet""" + return new_project(workspace) + + +def new_project(workspace) -> rope.Project: + """ + Always create a new Project, some operations like rename seems to have + problems when using the cached Project + """ fscommands = WorkspaceFileCommands(workspace) return rope.Project(workspace.root_path, fscommands=fscommands) def get_resource( - workspace, document_uri: DocumentUri + workspace, + document_uri: DocumentUri, + *, + project: rope.Project = None, ) -> Tuple[workspace.Document, rope.Resource]: + """ + Return a Document and Resource related to an LSP Document. + + `project` must be provided if not using instances of rope Project from + `pylsp_rope.project.get_project()`. + """ document = workspace.get_document(document_uri) - resource = libutils.path_to_resource(get_project(workspace), document.path) + project = project or get_project(workspace) + resource = libutils.path_to_resource(project, document.path) return document, resource