Skip to content

Commit 517d0fb

Browse files
authored
Fixes #1542: Add a status indication on how long the ESLint validation took. That is especially helpful for fix on save (#1570)
1 parent f095ba5 commit 517d0fb

File tree

4 files changed

+58
-13
lines changed

4 files changed

+58
-13
lines changed

$shared/customMessages.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export enum Status {
1414
export type StatusParams = {
1515
uri: string;
1616
state: Status;
17+
validationTime?: number;
1718
};
1819

1920
/**

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ This section describes major releases and their improvements. For a detailed lis
2323

2424
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.
2525

26+
### Version 2.3.1 - Pre-release
27+
28+
- the extension uses now VS Code's language status indicator
29+
- 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.
30+
2631
### Version 2.3.0 - Pre-release
2732

2833
- support for flat config files

client/src/client.ts

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import * as path from 'path';
88

99
import {
10-
workspace as Workspace, window as Window, languages as Languages, Uri, TextDocument, CodeActionContext, Diagnostic, ProviderResult,
10+
workspace as Workspace, window as Window, languages as Languages, Uri, TextDocument, CodeActionContext, Diagnostic,
1111
Command, CodeAction, MessageItem, ConfigurationTarget, env as Env, CodeActionKind, WorkspaceConfiguration, NotebookCell, commands,
1212
ExtensionContext, LanguageStatusItem, LanguageStatusSeverity, DocumentFilter as VDocumentFilter
1313
} from 'vscode';
@@ -151,7 +151,11 @@ export namespace ESLintClient {
151151
languageStatus.name = 'ESLint';
152152
languageStatus.text = 'ESLint';
153153
languageStatus.command = { title: 'Open ESLint Output', command: 'eslint.showOutputChannel' };
154-
const documentStatus: Map<string, Status> = new Map();
154+
type StatusInfo = Omit<StatusParams, 'uri'> & {
155+
firstReport: boolean;
156+
fixTime?: number;
157+
};
158+
const documentStatus: Map<string, StatusInfo> = new Map();
155159

156160
// If the workspace configuration changes we need to update the synced documents since the
157161
// list of probe language type can change.
@@ -492,7 +496,7 @@ export namespace ESLintClient {
492496
return next(document, cells);
493497
}
494498
},
495-
provideCodeActions: (document, range, context, token, next): ProviderResult<(Command | CodeAction)[]> => {
499+
provideCodeActions: async (document, range, context, token, next): Promise<(Command | CodeAction)[] | null | undefined> => {
496500
if (!syncedDocuments.has(document.uri.toString())) {
497501
return [];
498502
}
@@ -512,7 +516,20 @@ export namespace ESLintClient {
512516
return [];
513517
}
514518
const newContext: CodeActionContext = Object.assign({}, context, { diagnostics: eslintDiagnostics });
515-
return next(document, range, newContext, token);
519+
const start = Date.now();
520+
const result = await next(document, range, newContext, token);
521+
if (context.only?.value.startsWith('source.fixAll')) {
522+
const statusInfo = documentStatus.get(document.uri.toString());
523+
if (statusInfo !== undefined) {
524+
if (statusInfo.firstReport === true) {
525+
statusInfo.firstReport = false;
526+
statusInfo.validationTime = 0;
527+
}
528+
statusInfo.fixTime = Date.now() - start;
529+
updateStatusBar(document.uri.toString());
530+
}
531+
}
532+
return result;
516533
},
517534
workspace: {
518535
didChangeWatchedFile: (event, next) => {
@@ -769,9 +786,9 @@ export namespace ESLintClient {
769786
}
770787

771788
function updateDocumentStatus(params: StatusParams): void {
772-
const needsUpdate = !documentStatus.has(params.uri);
773-
documentStatus.set(params.uri, params.state);
774-
if (needsUpdate) {
789+
const hasStatus = documentStatus.has(params.uri);
790+
documentStatus.set(params.uri, Object.assign({}, params, { firstReport: !hasStatus }));
791+
if (!hasStatus) {
775792
updateLanguageStatusSelector();
776793
}
777794
updateStatusBar(params.uri);
@@ -793,18 +810,21 @@ export namespace ESLintClient {
793810
}
794811

795812
function updateStatusBar(uri: string | undefined) {
796-
const status = function() {
813+
const statusInfo = function(): StatusInfo {
797814
if (serverRunning === false) {
798-
return Status.error;
815+
return { state: Status.error, firstReport: true };
799816
}
800817
if (uri === undefined) {
801818
uri = Window.activeTextEditor?.document.uri.toString();
802819
}
803-
return (uri !== undefined ? documentStatus.get(uri) : undefined) ?? Status.ok;
820+
const params = uri !== undefined ? documentStatus.get(uri) : undefined;
821+
return params ?? { state: Status.ok, firstReport: true };
804822
}();
805-
let text: string = 'ESLint';
823+
824+
const timeTaken = statusInfo.firstReport ? -1 : Math.max(statusInfo.validationTime ?? -1, statusInfo.fixTime ?? -1);
825+
const text: string = timeTaken > 250 ? `ESLint [${timeTaken}ms]` : 'ESLint';
806826
let severity: LanguageStatusSeverity = LanguageStatusSeverity.Information;
807-
switch (status) {
827+
switch (statusInfo.state) {
808828
case Status.ok:
809829
break;
810830
case Status.warn:
@@ -814,6 +834,23 @@ export namespace ESLintClient {
814834
severity = LanguageStatusSeverity.Error;
815835
break;
816836
}
837+
if (severity === LanguageStatusSeverity.Information && timeTaken > 250) {
838+
severity = LanguageStatusSeverity.Warning;
839+
}
840+
if (severity === LanguageStatusSeverity.Warning && timeTaken > 750) {
841+
severity = LanguageStatusSeverity.Error;
842+
}
843+
if (timeTaken > 250) {
844+
const message = (statusInfo.validationTime ?? 0) > (statusInfo.fixTime ?? 0)
845+
? `Linting file ${uri} took ${timeTaken}ms`
846+
: `Computing fixes for file ${uri} during save took ${timeTaken}ms`;
847+
if (timeTaken > 750) {
848+
client.error(message);
849+
} else {
850+
client.warn(message);
851+
}
852+
}
853+
817854
languageStatus.text = text;
818855
languageStatus.severity = severity;
819856
}

server/src/eslintServer.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,11 +451,13 @@ async function validateSingle(document: TextDocument, publishDiagnostics: boolea
451451
return;
452452
}
453453
try {
454+
const start = Date.now();
454455
const diagnostics = await ESLint.validate(document, settings);
455456
if (publishDiagnostics) {
456457
void connection.sendDiagnostics({ uri: document.uri, diagnostics });
457458
}
458-
void connection.sendNotification(StatusNotification.type, { uri: document.uri, state: Status.ok });
459+
const timeTaken = Date.now() - start;
460+
void connection.sendNotification(StatusNotification.type, { uri: document.uri, state: Status.ok, validationTime: timeTaken });
459461
} catch (err) {
460462
// if an exception has occurred while validating clear all errors to ensure
461463
// we are not showing any stale once

0 commit comments

Comments
 (0)