Skip to content

Commit 4ecaca8

Browse files
authored
refactor task running on save (#2384)
1 parent 5923210 commit 4ecaca8

File tree

1 file changed

+51
-30
lines changed

1 file changed

+51
-30
lines changed

plugin/save_command.py

+51-30
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from .core.registry import LspTextCommand
22
from .core.settings import userprefs
3-
from .core.typing import Any, Callable, Dict, List, Type
3+
from .core.typing import Any, Callable, Dict, List, Optional, Type
44
from abc import ABCMeta, abstractmethod
5+
from functools import partial
56
import sublime
67
import sublime_plugin
78

@@ -60,6 +61,47 @@ def _purge_changes_async(self) -> None:
6061
break
6162

6263

64+
class SaveTasksRunner:
65+
def __init__(
66+
self, text_command: LspTextCommand, tasks: List[Type[SaveTask]], on_complete: Callable[[], None]
67+
) -> None:
68+
self._text_command = text_command
69+
self._tasks = tasks
70+
self._on_tasks_completed = on_complete
71+
self._pending_tasks = [] # type: List[SaveTask]
72+
self._canceled = False
73+
74+
def run(self) -> None:
75+
for task in self._tasks:
76+
if task.is_applicable(self._text_command.view):
77+
self._pending_tasks.append(task(self._text_command, self._on_task_completed_async))
78+
self._process_next_task()
79+
80+
def cancel(self) -> None:
81+
for task in self._pending_tasks:
82+
task.cancel()
83+
self._pending_tasks = []
84+
self._canceled = True
85+
86+
def _process_next_task(self) -> None:
87+
if self._pending_tasks:
88+
# Even though we might be on an async thread already, we want to give ST a chance to notify us about
89+
# potential document changes.
90+
sublime.set_timeout_async(self._run_next_task_async)
91+
else:
92+
self._on_tasks_completed()
93+
94+
def _run_next_task_async(self) -> None:
95+
if self._canceled:
96+
return
97+
current_task = self._pending_tasks[0]
98+
current_task.run_async()
99+
100+
def _on_task_completed_async(self) -> None:
101+
self._pending_tasks.pop(0)
102+
self._process_next_task()
103+
104+
63105
class LspSaveCommand(LspTextCommand):
64106
"""
65107
A command used as a substitute for native save command. Runs code actions and document
@@ -74,23 +116,14 @@ def register_task(cls, task: Type[SaveTask]) -> None:
74116

75117
def __init__(self, view: sublime.View) -> None:
76118
super().__init__(view)
77-
self._pending_tasks = [] # type: List[SaveTask]
78-
self._kwargs = {} # type: Dict[str, Any]
119+
self._save_tasks_runner = None # type: Optional[SaveTasksRunner]
79120

80121
def run(self, edit: sublime.Edit, **kwargs: Dict[str, Any]) -> None:
81-
if self._pending_tasks:
82-
for task in self._pending_tasks:
83-
task.cancel()
84-
self._pending_tasks = []
85-
self._kwargs = kwargs
122+
if self._save_tasks_runner:
123+
self._save_tasks_runner.cancel()
86124
sublime.set_timeout_async(self._trigger_on_pre_save_async)
87-
for Task in self._tasks:
88-
if Task.is_applicable(self.view):
89-
self._pending_tasks.append(Task(self, self._on_task_completed_async))
90-
if self._pending_tasks:
91-
sublime.set_timeout_async(self._run_next_task_async)
92-
else:
93-
self._trigger_native_save()
125+
self._save_tasks_runner = SaveTasksRunner(self, self._tasks, partial(self._on_tasks_completed, kwargs))
126+
self._save_tasks_runner.run()
94127

95128
def _trigger_on_pre_save_async(self) -> None:
96129
# Supermassive hack that will go away later.
@@ -100,22 +133,10 @@ def _trigger_on_pre_save_async(self) -> None:
100133
listener.trigger_on_pre_save_async() # type: ignore
101134
break
102135

103-
def _run_next_task_async(self) -> None:
104-
current_task = self._pending_tasks[0]
105-
current_task.run_async()
106-
107-
def _on_task_completed_async(self) -> None:
108-
self._pending_tasks.pop(0)
109-
if self._pending_tasks:
110-
# Even though we are on the async thread already, we want to give ST a chance to notify us about
111-
# potential document changes.
112-
sublime.set_timeout_async(self._run_next_task_async)
113-
else:
114-
self._trigger_native_save()
115-
116-
def _trigger_native_save(self) -> None:
136+
def _on_tasks_completed(self, kwargs: Dict[str, Any]) -> None:
137+
self._save_tasks_runner = None
117138
# Triggered from set_timeout to preserve original semantics of on_pre_save handling
118-
sublime.set_timeout(lambda: self.view.run_command('save', self._kwargs))
139+
sublime.set_timeout(lambda: self.view.run_command('save', kwargs))
119140

120141

121142
class LspSaveAllCommand(sublime_plugin.WindowCommand):

0 commit comments

Comments
 (0)