1
1
from .core .registry import LspTextCommand
2
2
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
4
4
from abc import ABCMeta , abstractmethod
5
+ from functools import partial
5
6
import sublime
6
7
import sublime_plugin
7
8
@@ -60,6 +61,47 @@ def _purge_changes_async(self) -> None:
60
61
break
61
62
62
63
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
+
63
105
class LspSaveCommand (LspTextCommand ):
64
106
"""
65
107
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:
74
116
75
117
def __init__ (self , view : sublime .View ) -> None :
76
118
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]
79
120
80
121
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 ()
86
124
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 ()
94
127
95
128
def _trigger_on_pre_save_async (self ) -> None :
96
129
# Supermassive hack that will go away later.
@@ -100,22 +133,10 @@ def _trigger_on_pre_save_async(self) -> None:
100
133
listener .trigger_on_pre_save_async () # type: ignore
101
134
break
102
135
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
117
138
# 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 ))
119
140
120
141
121
142
class LspSaveAllCommand (sublime_plugin .WindowCommand ):
0 commit comments