Skip to content

Commit be264f0

Browse files
ivanwonderatscott
authored andcommitted
refactor: use built-in WorkDoneProgressReport to report NGCC progress (#1614)
Now the Angular extension implements the `WorkDoneProgressReport` by itself on the client-side to support the multi-report progress with different `tsconfig.json`, to show an error message, to dispose of the report progress, but it's already a built-in feature that can be used on the service side. On the service side, the built-in `WorkDoneProgressReport` will attach a unique token to the different report progress and clean the progress when the client is closing. On the service side, If an error report when running NGCC, the LSP also supports showing an error message in VSCode, but the ability to open the output channel is not supported(now the LSP only supports to open the document URI). This PR will only need to provide it. So the custom `WorkDoneProgressReport` can be removed on the client side. (cherry picked from commit 5157872)
1 parent c882afe commit be264f0

File tree

6 files changed

+38
-113
lines changed

6 files changed

+38
-113
lines changed

client/src/client.ts

Lines changed: 5 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@ import * as path from 'path';
1111
import * as vscode from 'vscode';
1212
import * as lsp from 'vscode-languageclient/node';
1313

14-
import {ProjectLoadingFinish, ProjectLoadingStart, SuggestStrictMode, SuggestStrictModeParams} from '../common/notifications';
15-
import {NgccProgress, NgccProgressToken, NgccProgressType} from '../common/progress';
14+
import {OpenOutputChannel, ProjectLoadingFinish, ProjectLoadingStart, SuggestStrictMode, SuggestStrictModeParams} from '../common/notifications';
1615
import {GetComponentsWithTemplateFile, GetTcbRequest, GetTemplateLocationForComponent, IsInAngularProject} from '../common/requests';
1716
import {resolve, Version} from '../common/resolver';
1817

1918
import {isInsideComponentDecorator, isInsideInlineTemplateRegion, isInsideStringLiteral} from './embedded_support';
20-
import {ProgressReporter} from './progress-reporter';
2119

2220
interface GetTcbResponse {
2321
uri: vscode.Uri;
@@ -222,7 +220,6 @@ export class AngularLanguageClient implements vscode.Disposable {
222220
// Must wait for the client to be ready before registering notification
223221
// handlers.
224222
this.disposables.push(registerNotificationHandlers(this.client));
225-
this.disposables.push(registerProgressHandlers(this.client));
226223
}
227224

228225
/**
@@ -358,45 +355,11 @@ function registerNotificationHandlers(client: lsp.LanguageClient): vscode.Dispos
358355
}
359356
}));
360357

361-
return vscode.Disposable.from(...disposables);
362-
}
358+
disposables.push(client.onNotification(OpenOutputChannel, () => {
359+
client.outputChannel.show();
360+
}));
363361

364-
function registerProgressHandlers(client: lsp.LanguageClient) {
365-
const progressReporters = new Map<string, ProgressReporter>();
366-
const disposable =
367-
client.onProgress(NgccProgressType, NgccProgressToken, async (params: NgccProgress) => {
368-
const {configFilePath} = params;
369-
if (!progressReporters.has(configFilePath)) {
370-
progressReporters.set(configFilePath, new ProgressReporter());
371-
}
372-
const reporter = progressReporters.get(configFilePath)!;
373-
if (params.done) {
374-
reporter.finish();
375-
progressReporters.delete(configFilePath);
376-
if (!params.success) {
377-
const selection = await vscode.window.showErrorMessage(
378-
`Angular extension might not work correctly because ngcc operation failed. ` +
379-
`Try to invoke ngcc manually by running 'npm/yarn run ngcc'. ` +
380-
`Please see the extension output for more information.`,
381-
'Show output',
382-
);
383-
if (selection) {
384-
client.outputChannel.show();
385-
}
386-
}
387-
} else {
388-
reporter.report(params.message);
389-
}
390-
});
391-
const reporterDisposer = vscode.Disposable.from({
392-
dispose() {
393-
for (const reporter of progressReporters.values()) {
394-
reporter.finish();
395-
}
396-
disposable.dispose();
397-
}
398-
});
399-
return reporterDisposer;
362+
return vscode.Disposable.from(...disposables);
400363
}
401364

402365
/**

client/src/progress-reporter.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

common/notifications.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,9 @@ export interface SuggestStrictModeParams {
2626

2727
export const SuggestStrictMode =
2828
new NotificationType<SuggestStrictModeParams>('angular/suggestStrictMode');
29+
30+
// Report the end of `NGCC` progress and Only used by the `ivy_spec.ts`.
31+
export const NgccProgressEnd =
32+
new NotificationType<{configFilePath: string}>('angular/NgccProgressEnd');
33+
34+
export const OpenOutputChannel = new NotificationType('angular/OpenOutputChannel');

common/progress.ts

Lines changed: 0 additions & 21 deletions
This file was deleted.

integration/lsp/ivy_spec.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ import {MessageConnection} from 'vscode-jsonrpc';
1212
import * as lsp from 'vscode-languageserver-protocol';
1313
import {URI} from 'vscode-uri';
1414

15-
import {ProjectLanguageService, ProjectLanguageServiceParams, SuggestStrictMode, SuggestStrictModeParams} from '../../common/notifications';
16-
import {NgccProgress, NgccProgressToken, NgccProgressType} from '../../common/progress';
15+
import {NgccProgressEnd, ProjectLanguageService, ProjectLanguageServiceParams, SuggestStrictMode, SuggestStrictModeParams} from '../../common/notifications';
1716
import {GetComponentsWithTemplateFile, GetTcbRequest, GetTemplateLocationForComponent, IsInAngularProject} from '../../common/requests';
1817
import {APP_COMPONENT, APP_COMPONENT_URI, FOO_COMPONENT, FOO_COMPONENT_URI, FOO_TEMPLATE, FOO_TEMPLATE_URI, PROJECT_PATH, TSCONFIG} from '../test_constants';
1918

@@ -650,10 +649,8 @@ describe('insert snippet text', () => {
650649

651650
function onNgccProgress(client: MessageConnection): Promise<string> {
652651
return new Promise(resolve => {
653-
client.onProgress(NgccProgressType, NgccProgressToken, (params: NgccProgress) => {
654-
if (params.done) {
655-
resolve(params.configFilePath);
656-
}
652+
client.onNotification(NgccProgressEnd, (params) => {
653+
resolve(params.configFilePath);
657654
});
658655
});
659656
}

server/src/session.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@ import {promisify} from 'util';
1212
import * as lsp from 'vscode-languageserver/node';
1313

1414
import {ServerOptions} from '../common/initialize';
15-
import {ProjectLanguageService, ProjectLoadingFinish, ProjectLoadingStart, SuggestStrictMode} from '../common/notifications';
16-
import {NgccProgressToken, NgccProgressType} from '../common/progress';
15+
import {NgccProgressEnd, OpenOutputChannel, ProjectLanguageService, ProjectLoadingFinish, ProjectLoadingStart, SuggestStrictMode} from '../common/notifications';
1716
import {GetComponentsWithTemplateFile, GetTcbParams, GetTcbRequest, GetTcbResponse, GetTemplateLocationForComponent, GetTemplateLocationForComponentParams, IsInAngularProject, IsInAngularProjectParams} from '../common/requests';
1817

1918
import {readNgCompletionData, tsCompletionEntryToLspCompletionItem} from './completion';
@@ -42,6 +41,10 @@ enum LanguageId {
4241
const EMPTY_RANGE = lsp.Range.create(0, 0, 0, 0);
4342
const setImmediateP = promisify(setImmediate);
4443

44+
enum NgccErrorMessageAction {
45+
showOutput,
46+
}
47+
4548
/**
4649
* Session is a wrapper around lsp.IConnection, with all the necessary protocol
4750
* handlers installed for Angular language service.
@@ -1164,41 +1167,45 @@ export class Session {
11641167
this.disableLanguageServiceForProject(project, 'ngcc is running');
11651168
const configFilePath = project.getConfigFilePath();
11661169

1167-
this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
1168-
done: false,
1169-
configFilePath,
1170-
message: `Running ngcc for ${configFilePath}`,
1171-
});
1170+
const progressReporter = await this.connection.window.createWorkDoneProgress();
11721171

1173-
let success = false;
1172+
progressReporter.begin('Angular', undefined, `Running ngcc for ${configFilePath}`);
11741173

11751174
try {
11761175
this.projectNgccQueue.push({project, done: false});
11771176
await resolveAndRunNgcc(configFilePath, {
11781177
report: (msg: string) => {
1179-
this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
1180-
done: false,
1181-
configFilePath,
1182-
message: msg,
1183-
});
1178+
progressReporter.report(msg);
11841179
},
11851180
});
1186-
success = true;
11871181
} catch (e) {
11881182
this.error(
11891183
`Failed to run ngcc for ${
11901184
configFilePath}, language service may not operate correctly:\n` +
11911185
` ${e.message}`);
1186+
1187+
this.connection.window
1188+
.showErrorMessage<{
1189+
action: NgccErrorMessageAction,
1190+
title: string,
1191+
}>(`Angular extension might not work correctly because ngcc operation failed. ` +
1192+
`Try to invoke ngcc manually by running 'npm/yarn run ngcc'. ` +
1193+
`Please see the extension output for more information.`,
1194+
{title: 'Show output', action: NgccErrorMessageAction.showOutput})
1195+
.then((selection) => {
1196+
if (selection?.action === NgccErrorMessageAction.showOutput) {
1197+
this.connection.sendNotification(OpenOutputChannel, {});
1198+
}
1199+
});
11921200
} finally {
11931201
const loadingStatus = this.projectNgccQueue.find(p => p.project === project);
11941202
if (loadingStatus !== undefined) {
11951203
loadingStatus.done = true;
11961204
}
1197-
this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
1198-
done: true,
1205+
this.connection.sendNotification(NgccProgressEnd, {
11991206
configFilePath,
1200-
success,
12011207
});
1208+
progressReporter.done();
12021209
}
12031210

12041211
// ngcc processes might finish out of order, but we need to re-enable the language service for

0 commit comments

Comments
 (0)