Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle no selection consistently #1646

Merged
merged 12 commits into from
Apr 23, 2021
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions plugin/code_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .core.settings import userprefs
from .core.typing import Any, List, Dict, Callable, Optional, Tuple, Union, Sequence
from .core.views import entire_content_region
from .core.views import first_selection
from .core.views import text_document_code_action_params
from .save_command import LspSaveCommand, SaveTask
import sublime
Expand Down Expand Up @@ -276,9 +277,8 @@ def run(self, edit: sublime.Edit, event: Optional[dict] = None, only_kinds: Opti
self.commands = [] # type: List[Tuple[str, str, CodeActionOrCommand]]
self.commands_by_config = {} # type: CodeActionsByConfigName
view = self.view
try:
region = view.sel()[0]
except IndexError:
region = first_selection(view)
if region is None:
return
listener = windows.listener_for_view(view)
if not listener:
Expand Down
20 changes: 12 additions & 8 deletions plugin/core/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@ def best_session(view: sublime.View, sessions: Iterable[Session], point: Optiona
windows = WindowRegistry(configs)


def get_position(view: sublime.View, event: Optional[dict] = None, point: Optional[int] = None) -> int:
def get_position(view: sublime.View, event: Optional[dict] = None, point: Optional[int] = None) -> Optional[int]:
if isinstance(point, int):
return point
if event is None:
return view.sel()[0].begin()
x, y = event.get("x"), event.get("y")
if x is not None and y is not None:
return view.window_to_text((x, y))
else:
if event:
x, y = event.get("x"), event.get("y")
if x is not None and y is not None:
return view.window_to_text((x, y))
try:
return view.sel()[0].begin()
except IndexError:
return None


class LspTextCommand(sublime_plugin.TextCommand):
Expand All @@ -63,7 +64,10 @@ class LspTextCommand(sublime_plugin.TextCommand):
def is_enabled(self, event: Optional[dict] = None, point: Optional[int] = None) -> bool:
if self.capability:
# At least one active session with the given capability must exist.
if not self.best_session(self.capability, get_position(self.view, event, point)):
position = get_position(self.view, event, point)
if position is None:
return False
if not self.best_session(self.capability, position):
return False
if self.session_name:
# There must exist an active session with the given (config) name.
Expand Down
6 changes: 6 additions & 0 deletions plugin/core/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,12 @@ def text_document_identifier(view_or_file_name: Union[str, sublime.View]) -> Dic
return {"uri": uri}


def first_selection(view: sublime.View) -> Optional[sublime.Region]:
if len(view.sel()):
return view.sel()[0]
return None
rwols marked this conversation as resolved.
Show resolved Hide resolved


def entire_content_region(view: sublime.View) -> sublime.Region:
return sublime.Region(0, view.size())

Expand Down
14 changes: 5 additions & 9 deletions plugin/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from .core.typing import Any, Callable, Optional, Dict, Generator, Iterable, List, Tuple, Union
from .core.views import DIAGNOSTIC_SEVERITY
from .core.views import document_color_params
from .core.views import first_selection
from .core.views import format_completion
from .core.views import lsp_color_to_phantom
from .core.views import make_command_link
Expand Down Expand Up @@ -598,9 +599,10 @@ def _is_in_higlighted_region(self, point: int) -> bool:
return False

def _do_highlights_async(self) -> None:
if not len(self.view.sel()):
region = first_selection(self.view)
if region is None:
return
point = self.view.sel()[0].b
point = region.b
session = self.session("documentHighlightProvider", point)
if session:
params = text_document_position_params(self.view, point)
Expand Down Expand Up @@ -806,19 +808,13 @@ def _update_stored_region_async(self) -> Tuple[bool, sublime.Region]:
:returns: A tuple with two elements. The second element is the new region, the first element signals whether
the previous region was different from the newly stored region.
"""
current_region = self._get_current_region_async()
current_region = first_selection(self.view)
if current_region is not None:
if self._stored_region != current_region:
self._stored_region = current_region
return True, current_region
return False, sublime.Region(-1, -1)

def _get_current_region_async(self) -> Optional[sublime.Region]:
try:
return self.view.sel()[0]
except IndexError:
return None

def _clear_session_views_async(self) -> None:
session_views = self._session_views

Expand Down
28 changes: 15 additions & 13 deletions plugin/execute_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .core.registry import LspTextCommand
from .core.registry import windows
from .core.typing import List, Optional, Any
from .core.views import first_selection
from .core.views import uri_from_view, offset_to_point, region_to_range, text_document_identifier


Expand Down Expand Up @@ -49,24 +50,25 @@ def handle_response(response: Any) -> None:

def _expand_variables(self, command_args: List[Any]) -> List[Any]:
view = self.view # type: sublime.View
region = view.sel()[0]
region = first_selection(view)
for i, arg in enumerate(command_args):
if arg in ["$document_id", "${document_id}"]:
command_args[i] = text_document_identifier(view)
elif arg in ["$file_uri", "${file_uri}"]:
command_args[i] = uri_from_view(view)
elif arg in ["$selection", "${selection}"]:
command_args[i] = view.substr(region)
elif arg in ["$offset", "${offset}"]:
command_args[i] = region.b
elif arg in ["$selection_begin", "${selection_begin}"]:
command_args[i] = region.begin()
elif arg in ["$selection_end", "${selection_end}"]:
command_args[i] = region.end()
elif arg in ["$position", "${position}"]:
command_args[i] = offset_to_point(view, region.b).to_lsp()
elif arg in ["$range", "${range}"]:
command_args[i] = region_to_range(view, region).to_lsp()
elif region is not None:
if arg in ["$selection", "${selection}"]:
command_args[i] = view.substr(region)
elif arg in ["$offset", "${offset}"]:
command_args[i] = region.b
elif arg in ["$selection_begin", "${selection_begin}"]:
command_args[i] = region.begin()
elif arg in ["$selection_end", "${selection_end}"]:
command_args[i] = region.end()
elif arg in ["$position", "${position}"]:
command_args[i] = offset_to_point(view, region.b).to_lsp()
elif arg in ["$range", "${range}"]:
command_args[i] = region_to_range(view, region).to_lsp()
window = view.window()
window_variables = window.extract_variables() if window else {}
return sublime.expand_variables(command_args, window_variables)
6 changes: 4 additions & 2 deletions plugin/formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .core.settings import userprefs
from .core.typing import Any, Callable, List, Optional, Iterator
from .core.views import entire_content_region
from .core.views import first_selection
from .core.views import text_document_formatting
from .core.views import text_document_range_formatting
from .core.views import will_save_wait_until
Expand Down Expand Up @@ -119,6 +120,7 @@ def is_enabled(self, event: Optional[dict] = None, point: Optional[int] = None)

def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None:
session = self.best_session(self.capability)
if session:
req = text_document_range_formatting(self.view, self.view.sel()[0])
selection = first_selection(self.view)
rwols marked this conversation as resolved.
Show resolved Hide resolved
if session and selection is not None:
req = text_document_range_formatting(self.view, selection)
session.send_request(req, lambda response: apply_response_to_view(response, self.view))
5 changes: 4 additions & 1 deletion plugin/goto.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ def run(
) -> None:
session = self.best_session(self.capability)
if session:
params = text_document_position_params(self.view, get_position(self.view, event, point))
position = get_position(self.view, event, point)
if position is None:
return
params = text_document_position_params(self.view, position)
session.send_request(
Request(self.method, params, self.view, progress=True),
# It's better to run this on the UI thread so we are guaranteed no AttributeErrors anywhere
Expand Down
10 changes: 9 additions & 1 deletion plugin/hover.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from .core.typing import List, Optional, Any, Dict, Tuple, Sequence
from .core.views import diagnostic_severity
from .core.views import format_diagnostic_for_html
from .core.views import first_selection
from .core.views import FORMAT_MARKED_STRING, FORMAT_MARKUP_CONTENT, minihtml
from .core.views import make_command_link
from .core.views import make_link
Expand Down Expand Up @@ -70,10 +71,17 @@ def run(
point: Optional[int] = None,
event: Optional[dict] = None
) -> None:
hover_point = point or self.view.sel()[0].begin()
temp_point = point
if temp_point is None:
region = first_selection(self.view)
if region is not None:
temp_point = region.begin()
if temp_point is None:
return
window = self.view.window()
if not window:
return
hover_point = temp_point
wm = windows.lookup(window)
self._base_dir = wm.get_project_path(self.view.file_name() or "")
self._hover = None # type: Optional[Any]
Expand Down
5 changes: 4 additions & 1 deletion plugin/references.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,10 @@ def run(self, edit: sublime.Edit, event: Optional[dict] = None, point: Optional[
session = self.best_session(self.capability)
file_path = self.view.file_name()
if session and file_path:
pos = get_position(self.view, event, point)
tmp_pos = get_position(self.view, event, point)
if tmp_pos is None:
return
pos = tmp_pos
Comment on lines +40 to +43
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to do this "tmp" stuff because python is weird. Or lambdas rather since they don't bind the variables so the type will revert to possibly being None

window = self.view.window()
if not window:
return
Expand Down
12 changes: 9 additions & 3 deletions plugin/rename.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from .core.registry import windows
from .core.types import PANEL_FILE_REGEX, PANEL_LINE_REGEX
from .core.typing import Any, Optional, Dict, List
from .core.views import range_to_region, get_line
from .core.views import first_selection, range_to_region, get_line
from .core.views import text_document_position_params
import os
import sublime
Expand Down Expand Up @@ -63,7 +63,10 @@ def input(self, args: dict) -> Optional[sublime_plugin.TextInputHandler]:
point = args.get("point")
# guess the symbol name
if not isinstance(point, int):
point = self.view.sel()[0].b
region = first_selection(self.view)
if region is None:
return None
point = region.b
placeholder = self.view.substr(self.view.word(point))
return RenameSymbolInputHandler(self.view, placeholder)
else:
Expand All @@ -79,7 +82,10 @@ def run(
point: Optional[int] = None
) -> None:
if position is None:
pos = get_position(self.view, event, point)
tmp_pos = get_position(self.view, event, point)
if tmp_pos is None:
return
pos = tmp_pos
rchl marked this conversation as resolved.
Show resolved Hide resolved
if new_name:
return self._do_rename(pos, new_name)
else:
Expand Down
5 changes: 4 additions & 1 deletion plugin/selection_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ def is_enabled(self, event: Optional[dict] = None, point: Optional[int] = None)
return True

def run(self, edit: sublime.Edit, event: Optional[dict] = None) -> None:
session = self.best_session(self.capability, get_position(self.view, event))
position = get_position(self.view, event)
if position is None:
return
session = self.best_session(self.capability, position)
if session:
params = selection_range_params(self.view)
self._regions.extend(self.view.sel())
Expand Down