Skip to content

refactor: use built-in WorkDoneProgressReport to report NGCC progress #1614

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

Merged
merged 1 commit into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from all 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
47 changes: 5 additions & 42 deletions client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,11 @@ import * as path from 'path';
import * as vscode from 'vscode';
import * as lsp from 'vscode-languageclient/node';

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

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

interface GetTcbResponse {
uri: vscode.Uri;
Expand Down Expand Up @@ -213,7 +211,6 @@ export class AngularLanguageClient implements vscode.Disposable {
// Must wait for the client to be ready before registering notification
// handlers.
this.disposables.push(registerNotificationHandlers(this.client));
this.disposables.push(registerProgressHandlers(this.client));
}

/**
Expand Down Expand Up @@ -349,45 +346,11 @@ function registerNotificationHandlers(client: lsp.LanguageClient): vscode.Dispos
}
}));

return vscode.Disposable.from(...disposables);
}
disposables.push(client.onNotification(OpenOutputChannel, () => {
client.outputChannel.show();
}));

function registerProgressHandlers(client: lsp.LanguageClient) {
const progressReporters = new Map<string, ProgressReporter>();
const disposable =
client.onProgress(NgccProgressType, NgccProgressToken, async (params: NgccProgress) => {
const {configFilePath} = params;
if (!progressReporters.has(configFilePath)) {
progressReporters.set(configFilePath, new ProgressReporter());
}
const reporter = progressReporters.get(configFilePath)!;
if (params.done) {
reporter.finish();
progressReporters.delete(configFilePath);
if (!params.success) {
const selection = await vscode.window.showErrorMessage(
`Angular extension might not work correctly because ngcc operation failed. ` +
`Try to invoke ngcc manually by running 'npm/yarn run ngcc'. ` +
`Please see the extension output for more information.`,
'Show output',
);
if (selection) {
client.outputChannel.show();
}
}
} else {
reporter.report(params.message);
}
});
const reporterDisposer = vscode.Disposable.from({
dispose() {
for (const reporter of progressReporters.values()) {
reporter.finish();
}
disposable.dispose();
}
});
return reporterDisposer;
return vscode.Disposable.from(...disposables);
}

/**
Expand Down
27 changes: 0 additions & 27 deletions client/src/progress-reporter.ts

This file was deleted.

6 changes: 6 additions & 0 deletions common/notifications.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,9 @@ export interface SuggestStrictModeParams {

export const SuggestStrictMode =
new NotificationType<SuggestStrictModeParams>('angular/suggestStrictMode');

// Report the end of `NGCC` progress and Only used by the `ivy_spec.ts`.
export const NgccProgressEnd =
new NotificationType<{configFilePath: string}>('angular/NgccProgressEnd');

export const OpenOutputChannel = new NotificationType('angular/OpenOutputChannel');
21 changes: 0 additions & 21 deletions common/progress.ts

This file was deleted.

9 changes: 3 additions & 6 deletions integration/lsp/ivy_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import {MessageConnection} from 'vscode-jsonrpc';
import * as lsp from 'vscode-languageserver-protocol';
import {URI} from 'vscode-uri';

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

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

function onNgccProgress(client: MessageConnection): Promise<string> {
return new Promise(resolve => {
client.onProgress(NgccProgressType, NgccProgressToken, (params: NgccProgress) => {
if (params.done) {
resolve(params.configFilePath);
}
client.onNotification(NgccProgressEnd, (params) => {
resolve(params.configFilePath);
});
});
}
Expand Down
41 changes: 24 additions & 17 deletions server/src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@ import {promisify} from 'util';
import * as lsp from 'vscode-languageserver/node';

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

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

enum NgccErrorMessageAction {
showOutput,
}

/**
* Session is a wrapper around lsp.IConnection, with all the necessary protocol
* handlers installed for Angular language service.
Expand Down Expand Up @@ -1164,41 +1167,45 @@ export class Session {
this.disableLanguageServiceForProject(project, 'ngcc is running');
const configFilePath = project.getConfigFilePath();

this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
done: false,
configFilePath,
message: `Running ngcc for ${configFilePath}`,
});
const progressReporter = await this.connection.window.createWorkDoneProgress();

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

try {
this.projectNgccQueue.push({project, done: false});
await resolveAndRunNgcc(configFilePath, {
report: (msg: string) => {
this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
done: false,
configFilePath,
message: msg,
});
progressReporter.report(msg);
},
});
success = true;
} catch (e) {
this.error(
`Failed to run ngcc for ${
configFilePath}, language service may not operate correctly:\n` +
` ${e.message}`);

this.connection.window
.showErrorMessage<{
action: NgccErrorMessageAction,
title: string,
}>(`Angular extension might not work correctly because ngcc operation failed. ` +
`Try to invoke ngcc manually by running 'npm/yarn run ngcc'. ` +
`Please see the extension output for more information.`,
{title: 'Show output', action: NgccErrorMessageAction.showOutput})
.then((selection) => {
if (selection?.action === NgccErrorMessageAction.showOutput) {
this.connection.sendNotification(OpenOutputChannel, {});
}
});
} finally {
const loadingStatus = this.projectNgccQueue.find(p => p.project === project);
if (loadingStatus !== undefined) {
loadingStatus.done = true;
}
this.connection.sendProgress(NgccProgressType, NgccProgressToken, {
done: true,
this.connection.sendNotification(NgccProgressEnd, {
configFilePath,
success,
});
progressReporter.done();
}

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