Skip to content

Commit

Permalink
Improve completion item typings (#1650)
Browse files Browse the repository at this point in the history
  • Loading branch information
predragnikolic authored Apr 28, 2021
1 parent c968b35 commit 37b0ca8
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 20 deletions.
12 changes: 7 additions & 5 deletions plugin/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def run_async() -> None:
def _format_documentation(self, content: Union[str, Dict[str, str]]) -> str:
return minihtml(self.view, content, allowed_formats=FORMAT_STRING | FORMAT_MARKUP_CONTENT)

def _handle_resolve_response_async(self, item: Optional[dict]) -> None:
def _handle_resolve_response_async(self, item: CompletionItem) -> None:
detail = ""
documentation = ""
if item:
Expand Down Expand Up @@ -69,7 +69,7 @@ def _on_navigate(self, url: str) -> None:

class LspCompleteCommand(sublime_plugin.TextCommand):

def epilogue(self, item: Dict[str, Any], session_name: Optional[str] = None) -> None:
def epilogue(self, item: CompletionItem, session_name: Optional[str] = None) -> None:
additional_edits = item.get('additionalTextEdits')
if additional_edits:
edits = [parse_text_edit(additional_edit) for additional_edit in additional_edits]
Expand Down Expand Up @@ -98,9 +98,11 @@ def run(self, edit: sublime.Edit, item: Any, session_name: Optional[str] = None)

class LspCompleteTextEditCommand(LspCompleteCommand):

def run(self, edit: sublime.Edit, item: Any, session_name: Optional[str] = None) -> None:
text_edit = item["textEdit"]
new_text = text_edit['newText']
def run(self, edit: sublime.Edit, item: CompletionItem, session_name: Optional[str] = None) -> None:
text_edit = item.get("textEdit")
if not text_edit:
return
new_text = text_edit["newText"]
edit_region = range_to_region(Range.from_lsp(text_edit['range']), self.view)
if item.get("insertTextFormat", InsertTextFormat.PlainText) == InsertTextFormat.Snippet:
for region in self.translated_regions(edit_region):
Expand Down
17 changes: 9 additions & 8 deletions plugin/core/edit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .logging import debug
from .open import open_file
from .promise import Promise
from .protocol import TextEdit as LspTextEdit, Position
from .typing import List, Dict, Any, Iterable, Optional, Tuple
from .url import uri_to_filename
from functools import partial
Expand All @@ -9,11 +10,11 @@


# tuple of start, end, newText, version
TextEdit = Tuple[Tuple[int, int], Tuple[int, int], str, Optional[int]]
TextEditTuple = Tuple[Tuple[int, int], Tuple[int, int], str, Optional[int]]


def parse_workspace_edit(workspace_edit: Dict[str, Any]) -> Dict[str, List[TextEdit]]:
changes = {} # type: Dict[str, List[TextEdit]]
def parse_workspace_edit(workspace_edit: Dict[str, Any]) -> Dict[str, List[TextEditTuple]]:
changes = {} # type: Dict[str, List[TextEditTuple]]
document_changes = workspace_edit.get('documentChanges')
if isinstance(document_changes, list):
for document_change in document_changes:
Expand All @@ -32,11 +33,11 @@ def parse_workspace_edit(workspace_edit: Dict[str, Any]) -> Dict[str, List[TextE
return changes


def parse_range(range: Dict[str, int]) -> Tuple[int, int]:
def parse_range(range: Position) -> Tuple[int, int]:
return range['line'], range['character']


def parse_text_edit(text_edit: Dict[str, Any], version: int = None) -> TextEdit:
def parse_text_edit(text_edit: LspTextEdit, version: int = None) -> TextEditTuple:
return (
parse_range(text_edit['range']['start']),
parse_range(text_edit['range']['end']),
Expand All @@ -46,7 +47,7 @@ def parse_text_edit(text_edit: Dict[str, Any], version: int = None) -> TextEdit:
)


def sort_by_application_order(changes: Iterable[TextEdit]) -> List[TextEdit]:
def sort_by_application_order(changes: Iterable[TextEditTuple]) -> List[TextEditTuple]:
# The spec reads:
# > However, it is possible that multiple edits have the same start position: multiple
# > inserts, or any number of inserts followed by a single remove or replace edit. If
Expand All @@ -58,12 +59,12 @@ def sort_by_application_order(changes: Iterable[TextEdit]) -> List[TextEdit]:
return list(sorted(changes, key=operator.itemgetter(0)))


def apply_workspace_edit(window: sublime.Window, changes: Dict[str, List[TextEdit]]) -> Promise:
def apply_workspace_edit(window: sublime.Window, changes: Dict[str, List[TextEditTuple]]) -> Promise:
"""Apply workspace edits. This function must be called from the main thread!"""
return Promise.all([open_file(window, fn).then(partial(_apply_edits, edits)) for fn, edits in changes.items()])


def _apply_edits(edits: List[TextEdit], view: Optional[sublime.View]) -> None:
def _apply_edits(edits: List[TextEditTuple], view: Optional[sublime.View]) -> None:
if view and view.is_valid():
# Text commands run blocking. After this call has returned the changes are applied.
view.run_command("lsp_apply_document_edit", {"changes": edits})
32 changes: 30 additions & 2 deletions plugin/core/protocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ class SignatureHelpTriggerKind:
ContentChange = 3


class InsertTextMode:
AsIs = 1
AdjustIndentation = 2


DocumentUri = str

Position = TypedDict('Position', {
Expand Down Expand Up @@ -171,7 +176,30 @@ class SignatureHelpTriggerKind:
'relatedInformation': List[DiagnosticRelatedInformation]
}, total=False)

CompletionItem = Dict[str, Any]
TextEdit = TypedDict('TextEdit', {
'newText': str,
'range': RangeLsp
}, total=True)

CompletionItem = TypedDict('CompletionItem', {
'additionalTextEdits': List[TextEdit],
'command': Command,
'commitCharacters': List[str],
'data': Any,
'deprecated': bool,
'detail': str,
'documentation': Union[str, Dict[str, str]],
'filterText': str,
'insertText': str,
'insertTextFormat': InsertTextFormat,
'insertTextMode': InsertTextMode,
'kind': int,
'label': str,
'preselect': bool,
'sortText': str,
'tags': List[CompletionItemTag],
'textEdit': TextEdit
}, total=False)

CompletionList = TypedDict('CompletionList', {
'isIncomplete': bool,
Expand Down Expand Up @@ -235,7 +263,7 @@ def documentHighlight(cls, params: Mapping[str, Any], view: sublime.View) -> 'Re
return Request("textDocument/documentHighlight", params, view)

@classmethod
def resolveCompletionItem(cls, params: Mapping[str, Any], view: sublime.View) -> 'Request':
def resolveCompletionItem(cls, params: CompletionItem, view: sublime.View) -> 'Request':
return Request("completionItem/resolve", params, view)

@classmethod
Expand Down
4 changes: 2 additions & 2 deletions plugin/edit.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sublime
import sublime_plugin
from .core.edit import sort_by_application_order, TextEdit
from .core.edit import sort_by_application_order, TextEditTuple
from .core.logging import debug
from .core.typing import List, Optional, Any, Generator
from contextlib import contextmanager
Expand All @@ -21,7 +21,7 @@ def temporary_setting(settings: sublime.Settings, key: str, val: Any) -> Generat

class LspApplyDocumentEditCommand(sublime_plugin.TextCommand):

def run(self, edit: Any, changes: Optional[List[TextEdit]] = None) -> None:
def run(self, edit: Any, changes: Optional[List[TextEditTuple]] = None) -> None:
# Apply the changes in reverse, so that we don't invalidate the range
# of any change that we haven't applied yet.
if not changes:
Expand Down
3 changes: 2 additions & 1 deletion plugin/formatting.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from .core.edit import parse_text_edit
from .core.protocol import TextEdit
from .core.registry import LspTextCommand
from .core.registry import sessions_for_view
from .core.sessions import Session
Expand All @@ -13,7 +14,7 @@
import sublime


def apply_response_to_view(response: Optional[List[dict]], view: sublime.View) -> None:
def apply_response_to_view(response: Optional[List[TextEdit]], view: sublime.View) -> None:
edits = list(parse_text_edit(change) for change in response) if response else []
view.run_command('lsp_apply_document_edit', {'changes': edits})

Expand Down
9 changes: 7 additions & 2 deletions plugin/rename.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .core.edit import apply_workspace_edit
from .core.edit import parse_workspace_edit
from .core.edit import TextEdit
from .core.edit import TextEditTuple
from .core.panels import ensure_panel
from .core.panels import PanelName
from .core.protocol import Range
Expand Down Expand Up @@ -163,7 +163,12 @@ def _get_relative_path(self, file_path: str) -> str:
else:
return file_path

def _render_rename_panel(self, changes: Dict[str, List[TextEdit]], total_changes: int, file_count: int) -> None:
def _render_rename_panel(
self,
changes: Dict[str, List[TextEditTuple]],
total_changes: int,
file_count: int
) -> None:
window = self.view.window()
if not window:
return
Expand Down

0 comments on commit 37b0ca8

Please sign in to comment.