Skip to content
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

Fixes #1542: Add a status indication on how long the ESLint validation took. That is especially helpful for fix on save #1570

Merged
merged 1 commit into from
Dec 16, 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
1 change: 1 addition & 0 deletions $shared/customMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export enum Status {
export type StatusParams = {
uri: string;
state: Status;
validationTime?: number;
};

/**
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
61 changes: 49 additions & 12 deletions client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -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<string, Status> = new Map();
type StatusInfo = Omit<StatusParams, 'uri'> & {
firstReport: boolean;
fixTime?: number;
};
const documentStatus: Map<string, StatusInfo> = new Map();

// If the workspace configuration changes we need to update the synced documents since the
// list of probe language type can change.
Expand Down Expand Up @@ -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 [];
}
Expand All @@ -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) => {
Expand Down Expand Up @@ -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);
Expand All @@ -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:
Expand All @@ -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;
}
Expand Down
4 changes: 3 additions & 1 deletion server/src/eslintServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down