Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit5c44eec

Browse files
authored
Fix issue with recovery from cpptools crash when using multiroot (microsoft#8810)
1 parent99ac776 commit5c44eec

File tree

2 files changed

+123
-45
lines changed

2 files changed

+123
-45
lines changed

‎Extension/src/LanguageServer/client.ts‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,7 @@ export interface Client {
689689
RootPath:string;
690690
RootRealPath:string;
691691
RootUri?:vscode.Uri;
692+
RootFolder?:vscode.WorkspaceFolder;
692693
Name:string;
693694
TrackedDocuments:Set<vscode.TextDocument>;
694695
onDidChangeSettings(event:vscode.ConfigurationChangeEvent,isFirstClient:boolean):{[key:string]:string};
@@ -1480,15 +1481,15 @@ export class DefaultClient implements Client {
14801481
languageClientCrashedNeedsRestart=true;
14811482
telemetry.logLanguageServerEvent("languageClientCrash");
14821483
if(languageClientCrashTimes.length<5){
1483-
allClients.forEach(client=>{allClients.replace(client,true);});
1484+
allClients.recreateClients(true);
14841485
}else{
14851486
constelapsed:number=languageClientCrashTimes[languageClientCrashTimes.length-1]-languageClientCrashTimes[0];
14861487
if(elapsed<=3*60*1000){
14871488
vscode.window.showErrorMessage(localize('server.crashed2',"The language server crashed 5 times in the last 3 minutes. It will not be restarted."));
1488-
allClients.forEach(client=>{allClients.replace(client,false);});
1489+
allClients.recreateClients(false);
14891490
}else{
14901491
languageClientCrashTimes.shift();
1491-
allClients.forEach(client=>{allClients.replace(client,true);});
1492+
allClients.recreateClients(true);
14921493
}
14931494
}
14941495
returnCloseAction.DoNotRestart;

‎Extension/src/LanguageServer/clientCollection.ts‎

Lines changed: 119 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -104,47 +104,52 @@ export class ClientCollection {
104104
/**
105105
* creates a new client to replace one that crashed.
106106
*/
107-
publicreplace(client:cpptools.Client,transferFileOwnership:boolean):cpptools.Client|undefined{
108-
letkey:string|undefined;
109-
for(constpairofthis.languageClients){
110-
if(pair[1]===client){
111-
key=pair[0];
112-
break;
113-
}
114-
}
107+
publicasyncrecreateClients(transferFileOwnership:boolean):Promise<void>{
108+
109+
// Swap out the map, so we are not changing it while iterating over it.
110+
constoldLanguageClients:Map<string,cpptools.Client>=this.languageClients;
111+
this.languageClients=newMap<string,cpptools.Client>();
115112

116-
if(key){
117-
this.languageClients.delete(key);
113+
for(constpairofoldLanguageClients){
114+
constclient:cpptools.Client=pair[1];
118115

116+
letnewClient:cpptools.Client;
119117
if(transferFileOwnership){
120-
// This will create a new Client for the workspace since we removed the old one fromthis.languageClients.
118+
newClient=this.createClient(client.RootFolder,true);
121119
client.TrackedDocuments.forEach(document=>this.transferOwnership(document,client));
122-
client.TrackedDocuments.clear();
123120
}else{
124-
// Create an empty client that will continue to "own" files matching this workspace, but ignore all messages from VS Code.
125-
this.languageClients.set(key,cpptools.createNullClient());
121+
newClient=cpptools.createNullClient();
122+
}
123+
124+
if(this.activeClient===client){
125+
// It cannot be undefined. If there is an active document, we activate it later.
126+
this.activeClient=newClient;
126127
}
127128

128-
if(this.activeClient===client&&this.activeDocument){
129-
this.activeClient=this.getClientFor(this.activeDocument.uri);
130-
this.activeClient.activeDocumentChanged(this.activeDocument);
129+
if(this.defaultClient===client){
130+
this.defaultClient=newClient;
131131
}
132132

133133
client.dispose();
134-
returnthis.languageClients.get(key);
135-
}else{
136-
console.assert(key,"unable to locate language client");
137-
returnundefined;
134+
}
135+
136+
if(this.activeDocument){
137+
this.activeClient=this.getClientFor(this.activeDocument.uri);
138+
awaitthis.activeClient.activeDocumentChanged(this.activeDocument);
139+
this.activeClient.activate();
138140
}
139141
}
140142

141-
privateonDidChangeWorkspaceFolders(e?:vscode.WorkspaceFoldersChangeEvent):void{
143+
privateasynconDidChangeWorkspaceFolders(e?:vscode.WorkspaceFoldersChangeEvent):Promise<void>{
142144
constfolderCount:number=vscode.workspace.workspaceFolders ?vscode.workspace.workspaceFolders.length :0;
143145
if(folderCount>1){
144146
telemetry.logLanguageServerEvent("workspaceFoldersChange",{"count":folderCount.toString()});
145147
}
146148

147149
if(e!==undefined){
150+
letoldDefaultClient:cpptools.Client|undefined;
151+
letneedNewDefaultClient:boolean=false;
152+
148153
e.removed.forEach(folder=>{
149154
constpath:string=util.asFolder(folder.uri);
150155
constclient:cpptools.Client|undefined=this.languageClients.get(path);
@@ -154,30 +159,90 @@ export class ClientCollection {
154159
// Transfer ownership of the client's documents to another client.
155160
// (this includes calling textDocument/didOpen on the new client so that the server knows it's open too)
156161
client.TrackedDocuments.forEach(document=>this.transferOwnership(document,client));
157-
client.TrackedDocuments.clear();
158-
159-
if(this.activeClient===client&&this.activeDocument){
160-
// Need to make a different client the active client.
161-
this.activeClient=this.getClientFor(this.activeDocument.uri);
162-
this.activeClient.activeDocumentChanged(this.activeDocument);
163-
// may not need this, the navigation UI should not have changed.
164-
// this.activeClient.selectionChanged(Range.create(vscode.window.activeTextEditor.selection.start, vscode.window.activeTextEditor.selection.end);
162+
163+
if(this.activeClient===client){
164+
this.activeClient.deactivate();
165165
}
166166

167-
client.dispose();
167+
// Defer selecting a new default client until all adds and removes have been processed.
168+
if(this.defaultClient===client){
169+
oldDefaultClient=client;
170+
}else{
171+
client.dispose();
172+
}
168173
}
169174
});
175+
170176
e.added.forEach(folder=>{
171177
constpath:string=util.asFolder(folder.uri);
172178
constclient:cpptools.Client|undefined=this.languageClients.get(path);
173179
if(!client){
174-
constnewClient:cpptools.Client=cpptools.createClient(this,folder);
175-
this.languageClients.set(path,newClient);
176-
newClient.deactivate();// e.g. prevent the current config from switching.
177-
constdefaultClient:cpptools.DefaultClient=<cpptools.DefaultClient>newClient;
178-
defaultClient.sendAllSettings();
180+
this.createClient(folder,true);
179181
}
180182
});
183+
184+
// Note: VS Code currently reloads the extension whenever the primary (first) workspace folder is added or removed.
185+
// So the following handling of changes to defaultClient are likely unnecessary, unless the behavior of
186+
// VS Code changes. The handling of changes to activeClient are still needed.
187+
188+
if(oldDefaultClient){
189+
consturi:vscode.Uri|undefined=oldDefaultClient.RootUri;
190+
// uri will be set.
191+
if(uri){
192+
// Check if there is now another more appropriate client to use.
193+
this.defaultClient=this.getClientFor(uri);
194+
needNewDefaultClient=this.defaultClient===oldDefaultClient;
195+
}
196+
oldDefaultClient.dispose();
197+
}else{
198+
constdefaultDefaultClient:cpptools.Client|undefined=this.languageClients.get(defaultClientKey);
199+
if(defaultDefaultClient){
200+
// If there is an entry in languageClients for defaultClientKey, we were not previously tracking any workspace folders.
201+
this.languageClients.delete(defaultClientKey);
202+
needNewDefaultClient=true;
203+
if(this.activeClient===this.defaultClient){
204+
// Redundant deactivation should be OK.
205+
this.activeClient.deactivate();
206+
}
207+
}
208+
}
209+
210+
if(needNewDefaultClient){
211+
// Use the first workspaceFolder, if any.
212+
if(vscode.workspace.workspaceFolders&&vscode.workspace.workspaceFolders.length>0){
213+
constkey:string=util.asFolder(vscode.workspace.workspaceFolders[0].uri);
214+
constclient:cpptools.Client|undefined=this.languageClients.get(key);
215+
if(!client){
216+
// This should not occur. If there is a workspace folder, we should have a client for it by now.
217+
thrownewError("Failed to construct default client");
218+
}
219+
this.defaultClient=client;
220+
}else{
221+
// The user removed the last workspace folder. Create a new default defaultClient/activeClient
222+
// using the same approach as used in the constructor.
223+
this.defaultClient=cpptools.createClient(this);
224+
this.languageClients.set(defaultClientKey,this.defaultClient);
225+
this.defaultClient.deactivate();
226+
if(this.activeDocument){
227+
// Only change activeClient if it would not be changed by the later check.
228+
this.activeClient.deactivate();
229+
this.activeClient=this.defaultClient;
230+
}
231+
}
232+
}
233+
234+
// Ensure the best client for the currently active document is activated.
235+
if(this.activeDocument){
236+
constnewActiveClient:cpptools.Client=this.getClientFor(this.activeDocument.uri);
237+
// If a client is newly created here, it will be activated by default.
238+
if(this.activeClient!==newActiveClient){
239+
// Redundant deactivate should be OK.
240+
this.activeClient.deactivate();
241+
this.activeClient=newActiveClient;
242+
awaitthis.activeClient.activeDocumentChanged(this.activeDocument);
243+
this.activeClient.activate();
244+
}
245+
}
181246
}
182247
}
183248

@@ -190,6 +255,10 @@ export class ClientCollection {
190255

191256
publicgetClientFor(uri:vscode.Uri):cpptools.Client{
192257
constfolder:vscode.WorkspaceFolder|undefined=uri ?vscode.workspace.getWorkspaceFolder(uri) :undefined;
258+
returnthis.getClientForFolder(folder);
259+
}
260+
261+
publicgetClientForFolder(folder?:vscode.WorkspaceFolder):cpptools.Client{
193262
if(!folder){
194263
returnthis.defaultClient;
195264
}else{
@@ -198,13 +267,21 @@ export class ClientCollection {
198267
if(client){
199268
returnclient;
200269
}
201-
constnewClient:cpptools.Client=cpptools.createClient(this,folder);
202-
this.languageClients.set(key,newClient);
203-
getCustomConfigProviders().forEach(provider=>newClient.onRegisterCustomConfigurationProvider(provider));
204-
constdefaultClient:cpptools.DefaultClient=<cpptools.DefaultClient>newClient;
205-
defaultClient.sendAllSettings();
206-
returnnewClient;
270+
returnthis.createClient(folder);
271+
}
272+
}
273+
274+
publiccreateClient(folder?:vscode.WorkspaceFolder,deactivated?:boolean):cpptools.Client{
275+
constnewClient:cpptools.Client=cpptools.createClient(this,folder);
276+
if(deactivated){
277+
newClient.deactivate();// e.g. prevent the current config from switching.
207278
}
279+
constkey:string=folder ?util.asFolder(folder.uri) :defaultClientKey;
280+
this.languageClients.set(key,newClient);
281+
getCustomConfigProviders().forEach(provider=>newClient.onRegisterCustomConfigurationProvider(provider));
282+
constdefaultClient:cpptools.DefaultClient=<cpptools.DefaultClient>newClient;
283+
defaultClient.sendAllSettings();
284+
returnnewClient;
208285
}
209286

210287
privateonDidCloseTextDocument(document:vscode.TextDocument):void{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp