From 5d915cf6a0c2b7219f92a10e2c08fd854bb6acf3 Mon Sep 17 00:00:00 2001 From: Dirk Baeumer Date: Fri, 16 Dec 2022 10:50:44 +0100 Subject: [PATCH] Fixes #1542: Add a status indication on how long the ESLint validation took. That is especially helpful for fix on save --- $shared/customMessages.ts | 1 + README.md | 5 ++++ client/src/client.ts | 61 ++++++++++++++++++++++++++++++-------- server/src/eslintServer.ts | 4 ++- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/$shared/customMessages.ts b/$shared/customMessages.ts index 5302382a..a452f0b9 100644 --- a/$shared/customMessages.ts +++ b/$shared/customMessages.ts @@ -14,6 +14,7 @@ export enum Status { export type StatusParams = { uri: string; state: Status; + validationTime?: number; }; /** diff --git a/README.md b/README.md index 88485a0b..538798a9 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,11 @@ This section describes major releases and their improvements. For a detailed lis From version 2.2.3 on forward odd major, minor or patch version numbers indicate an insider or pre-release. So versions `2.2.3`, `2.2.5`, `2.3.1` and `3.0.0` will all be pre-release versions. `2.2.10`, `2.4.10` and `4.0.0` will all be regular release versions. +### Version 2.3.1 - Pre-release + +- the extension uses now VS Code's language status indicator +- the language status indicator now informs about long linting or fix on save times. Times above 750ms produce an error indication and times above 250ms a warning indication. + ### Version 2.3.0 - Pre-release - support for flat config files diff --git a/client/src/client.ts b/client/src/client.ts index ca27be03..a7595043 100644 --- a/client/src/client.ts +++ b/client/src/client.ts @@ -7,7 +7,7 @@ import * as path from 'path'; import { - workspace as Workspace, window as Window, languages as Languages, Uri, TextDocument, CodeActionContext, Diagnostic, ProviderResult, + workspace as Workspace, window as Window, languages as Languages, Uri, TextDocument, CodeActionContext, Diagnostic, Command, CodeAction, MessageItem, ConfigurationTarget, env as Env, CodeActionKind, WorkspaceConfiguration, NotebookCell, commands, ExtensionContext, LanguageStatusItem, LanguageStatusSeverity, DocumentFilter as VDocumentFilter } from 'vscode'; @@ -151,7 +151,11 @@ export namespace ESLintClient { languageStatus.name = 'ESLint'; languageStatus.text = 'ESLint'; languageStatus.command = { title: 'Open ESLint Output', command: 'eslint.showOutputChannel' }; - const documentStatus: Map = new Map(); + type StatusInfo = Omit & { + firstReport: boolean; + fixTime?: number; + }; + const documentStatus: Map = new Map(); // If the workspace configuration changes we need to update the synced documents since the // list of probe language type can change. @@ -492,7 +496,7 @@ export namespace ESLintClient { return next(document, cells); } }, - provideCodeActions: (document, range, context, token, next): ProviderResult<(Command | CodeAction)[]> => { + provideCodeActions: async (document, range, context, token, next): Promise<(Command | CodeAction)[] | null | undefined> => { if (!syncedDocuments.has(document.uri.toString())) { return []; } @@ -512,7 +516,20 @@ export namespace ESLintClient { return []; } const newContext: CodeActionContext = Object.assign({}, context, { diagnostics: eslintDiagnostics }); - return next(document, range, newContext, token); + const start = Date.now(); + const result = await next(document, range, newContext, token); + if (context.only?.value.startsWith('source.fixAll')) { + const statusInfo = documentStatus.get(document.uri.toString()); + if (statusInfo !== undefined) { + if (statusInfo.firstReport === true) { + statusInfo.firstReport = false; + statusInfo.validationTime = 0; + } + statusInfo.fixTime = Date.now() - start; + updateStatusBar(document.uri.toString()); + } + } + return result; }, workspace: { didChangeWatchedFile: (event, next) => { @@ -769,9 +786,9 @@ export namespace ESLintClient { } function updateDocumentStatus(params: StatusParams): void { - const needsUpdate = !documentStatus.has(params.uri); - documentStatus.set(params.uri, params.state); - if (needsUpdate) { + const hasStatus = documentStatus.has(params.uri); + documentStatus.set(params.uri, Object.assign({}, params, { firstReport: !hasStatus })); + if (!hasStatus) { updateLanguageStatusSelector(); } updateStatusBar(params.uri); @@ -793,18 +810,21 @@ export namespace ESLintClient { } function updateStatusBar(uri: string | undefined) { - const status = function() { + const statusInfo = function(): StatusInfo { if (serverRunning === false) { - return Status.error; + return { state: Status.error, firstReport: true }; } if (uri === undefined) { uri = Window.activeTextEditor?.document.uri.toString(); } - return (uri !== undefined ? documentStatus.get(uri) : undefined) ?? Status.ok; + const params = uri !== undefined ? documentStatus.get(uri) : undefined; + return params ?? { state: Status.ok, firstReport: true }; }(); - let text: string = 'ESLint'; + + const timeTaken = statusInfo.firstReport ? -1 : Math.max(statusInfo.validationTime ?? -1, statusInfo.fixTime ?? -1); + const text: string = timeTaken > 250 ? `ESLint [${timeTaken}ms]` : 'ESLint'; let severity: LanguageStatusSeverity = LanguageStatusSeverity.Information; - switch (status) { + switch (statusInfo.state) { case Status.ok: break; case Status.warn: @@ -814,6 +834,23 @@ export namespace ESLintClient { severity = LanguageStatusSeverity.Error; break; } + if (severity === LanguageStatusSeverity.Information && timeTaken > 250) { + severity = LanguageStatusSeverity.Warning; + } + if (severity === LanguageStatusSeverity.Warning && timeTaken > 750) { + severity = LanguageStatusSeverity.Error; + } + if (timeTaken > 250) { + const message = (statusInfo.validationTime ?? 0) > (statusInfo.fixTime ?? 0) + ? `Linting file ${uri} took ${timeTaken}ms` + : `Computing fixes for file ${uri} during save took ${timeTaken}ms`; + if (timeTaken > 750) { + client.error(message); + } else { + client.warn(message); + } + } + languageStatus.text = text; languageStatus.severity = severity; } diff --git a/server/src/eslintServer.ts b/server/src/eslintServer.ts index c541f5d3..d7577427 100644 --- a/server/src/eslintServer.ts +++ b/server/src/eslintServer.ts @@ -451,11 +451,13 @@ async function validateSingle(document: TextDocument, publishDiagnostics: boolea return; } try { + const start = Date.now(); const diagnostics = await ESLint.validate(document, settings); if (publishDiagnostics) { void connection.sendDiagnostics({ uri: document.uri, diagnostics }); } - void connection.sendNotification(StatusNotification.type, { uri: document.uri, state: Status.ok }); + const timeTaken = Date.now() - start; + void connection.sendNotification(StatusNotification.type, { uri: document.uri, state: Status.ok, validationTime: timeTaken }); } catch (err) { // if an exception has occurred while validating clear all errors to ensure // we are not showing any stale once