vscode-eslint 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/vscode-eslint +82 -0
- package/client/out/client.d.ts +13 -0
- package/client/out/extension.d.ts +3 -0
- package/client/out/extension.js +2 -0
- package/client/out/extension.js.map +1 -0
- package/client/out/node-utils.d.ts +51 -0
- package/client/out/settings.d.ts +41 -0
- package/client/out/shared/customMessages.d.ts +89 -0
- package/client/out/shared/settings.d.ts +106 -0
- package/client/out/tasks.d.ts +31 -0
- package/client/out/tests/glob.test.d.ts +1 -0
- package/client/out/vscode-utils.d.ts +5 -0
- package/package.json +9 -2
- package/server/out/diff.d.ts +134 -0
- package/server/out/eslint.d.ts +298 -0
- package/server/out/eslintServer.d.ts +1 -0
- package/server/out/eslintServer.js +2 -0
- package/server/out/eslintServer.js.map +1 -0
- package/server/out/is.d.ts +3 -0
- package/server/out/languageDefaults.d.ts +6 -0
- package/server/out/linkedMap.d.ts +53 -0
- package/server/out/paths.d.ts +22 -0
- package/server/out/shared/customMessages.d.ts +89 -0
- package/server/out/shared/settings.d.ts +106 -0
- package/$shared/customMessages.ts +0 -113
- package/$shared/settings.ts +0 -189
- package/.CodeQL.yml +0 -5
- package/.azure-pipelines.yml +0 -27
- package/.gemini/agents/vscode-eslint.md +0 -23
- package/.github/commands.yml +0 -127
- package/.github/locker.yml +0 -6
- package/.github/needs_more_info.yml +0 -6
- package/.github/workflows/npm-publish.yml +0 -53
- package/.github/workflows/release-please.yml +0 -22
- package/.lsifrc.json +0 -4
- package/.vscode/launch.json +0 -20
- package/.vscode/settings.json +0 -52
- package/.vscode/spellright.dict +0 -8
- package/.vscode/tasks.json +0 -39
- package/.vscodeignore +0 -23
- package/CHANGELOG.md +0 -524
- package/SECURITY.md +0 -41
- package/agents.md +0 -36
- package/bin/vscode-eslint.js +0 -56
- package/build/azure-pipelines/linux/build.yml +0 -14
- package/build/azure-pipelines/pre-release.yml +0 -42
- package/build/azure-pipelines/release.yml +0 -45
- package/build/azure-pipelines/win32/build.yml +0 -14
- package/build/bin/all.js +0 -29
- package/build/bin/linking.js +0 -102
- package/build/bin/symlink.js +0 -35
- package/client/.mocharc.json +0 -6
- package/client/agents.md +0 -5
- package/client/package-lock.json +0 -176
- package/client/package.json +0 -29
- package/client/src/client.ts +0 -992
- package/client/src/extension.ts +0 -180
- package/client/src/node-utils.ts +0 -393
- package/client/src/settings.ts +0 -379
- package/client/src/tasks.ts +0 -186
- package/client/src/tests/glob.test.ts +0 -31
- package/client/src/vscode-utils.ts +0 -28
- package/client/test/mocha.opts +0 -3
- package/client/tsconfig.json +0 -20
- package/client/webpack.config.js +0 -25
- package/contributing.md +0 -19
- package/esbuild.js +0 -62
- package/eslint.config.js +0 -129
- package/history/settings_1_9_x.md +0 -110
- package/images/2_1_10/eslint-dialog.png +0 -0
- package/images/2_1_10/eslint-status.png +0 -0
- package/package-json-schema.json +0 -9
- package/playgrounds/7.0/.eslintignore +0 -1
- package/playgrounds/7.0/.eslintrc.json +0 -71
- package/playgrounds/7.0/.vscode/settings.json +0 -85
- package/playgrounds/7.0/app.js +0 -12
- package/playgrounds/7.0/build/.eslintignore +0 -1
- package/playgrounds/7.0/build/.eslintrc.json +0 -30
- package/playgrounds/7.0/build/build.js +0 -11
- package/playgrounds/7.0/jsconfig.json +0 -5
- package/playgrounds/7.0/package-lock.json +0 -2133
- package/playgrounds/7.0/package.json +0 -10
- package/playgrounds/7.0/readme.md +0 -0
- package/playgrounds/7.0/subDir/sub.js +0 -11
- package/playgrounds/7.0/subDir/test.jsx +0 -10
- package/playgrounds/7.0/test.js +0 -11
- package/playgrounds/7.0/test.sh +0 -1
- package/playgrounds/7.0/test.vue +0 -33
- package/playgrounds/7.0/test2.html +0 -8
- package/playgrounds/8.0/.eslintignore +0 -1
- package/playgrounds/8.0/.eslintrc.json +0 -71
- package/playgrounds/8.0/.vscode/settings.json +0 -91
- package/playgrounds/8.0/app.js +0 -12
- package/playgrounds/8.0/build/.eslintignore +0 -1
- package/playgrounds/8.0/build/.eslintrc.json +0 -30
- package/playgrounds/8.0/build/build.js +0 -11
- package/playgrounds/8.0/jsconfig.json +0 -5
- package/playgrounds/8.0/package-lock.json +0 -2321
- package/playgrounds/8.0/package.json +0 -10
- package/playgrounds/8.0/readme.md +0 -17
- package/playgrounds/8.0/subDir/sub.js +0 -11
- package/playgrounds/8.0/subDir/test.jsx +0 -10
- package/playgrounds/8.0/test.ipynb +0 -49
- package/playgrounds/8.0/test.js +0 -3
- package/playgrounds/8.0/test.sh +0 -1
- package/playgrounds/8.0/test.vue +0 -33
- package/playgrounds/8.0/test2.html +0 -8
- package/playgrounds/9.0/flat/.vscode/settings.json +0 -3
- package/playgrounds/9.0/flat/app.js +0 -12
- package/playgrounds/9.0/flat/dist/ignore.js +0 -12
- package/playgrounds/9.0/flat/eslint.config.js +0 -61
- package/playgrounds/9.0/flat/package-lock.json +0 -1053
- package/playgrounds/9.0/flat/package.json +0 -9
- package/playgrounds/9.0/rc/.eslintrc.json +0 -57
- package/playgrounds/9.0/rc/.vscode/settings.json +0 -3
- package/playgrounds/9.0/rc/app.js +0 -12
- package/playgrounds/9.0/rc/package-lock.json +0 -1345
- package/playgrounds/9.0/rc/package.json +0 -9
- package/playgrounds/flat-config/.vscode/settings.json +0 -22
- package/playgrounds/flat-config/app.js +0 -12
- package/playgrounds/flat-config/eslint.config.js +0 -51
- package/playgrounds/flat-config/package-lock.json +0 -2733
- package/playgrounds/flat-config/package.json +0 -12
- package/playgrounds/flat-config/sub/sub.js +0 -2
- package/playgrounds/flat-config/test.ts +0 -7
- package/playgrounds/flat-config/tsconfig.json +0 -11
- package/playgrounds/flat-config-fail/f1/app.js +0 -12
- package/playgrounds/flat-config-fail/f1/eslint.config.js +0 -51
- package/playgrounds/flat-config-fail/package-lock.json +0 -1683
- package/playgrounds/flat-config-fail/package.json +0 -11
- package/playgrounds/flat-config-mjs/.vscode/settings.json +0 -21
- package/playgrounds/flat-config-mjs/app.js +0 -12
- package/playgrounds/flat-config-mjs/eslint.config.mjs +0 -53
- package/playgrounds/flat-config-mjs/package-lock.json +0 -2860
- package/playgrounds/flat-config-mjs/package.json +0 -11
- package/playgrounds/flat-config-mjs/sub/sub.js +0 -2
- package/playgrounds/flat-config-mjs/test.ts +0 -7
- package/playgrounds/flat-config-mjs/tsconfig.json +0 -11
- package/playgrounds/load-eslint/.vscode/settings.json +0 -21
- package/playgrounds/load-eslint/app.js +0 -12
- package/playgrounds/load-eslint/eslint.config.js +0 -51
- package/playgrounds/load-eslint/package-lock.json +0 -2860
- package/playgrounds/load-eslint/package.json +0 -11
- package/playgrounds/load-eslint/sub/sub.js +0 -2
- package/playgrounds/load-eslint/test.ts +0 -7
- package/playgrounds/load-eslint/tsconfig.json +0 -11
- package/playgrounds/noLib/test.js +0 -22
- package/playgrounds/noWD/.vscode/settings.json +0 -2
- package/playgrounds/noWD/src/.eslintrc.json +0 -18
- package/playgrounds/noWD/src/package-lock.json +0 -2812
- package/playgrounds/noWD/src/package.json +0 -12
- package/playgrounds/noWD/src/test.js +0 -3
- package/playgrounds/notebooks/notebook.ipynb +0 -7072
- package/playgrounds/notebooks/notebook2.ipynb +0 -20
- package/playgrounds/testing.code-workspace +0 -28
- package/playgrounds/ts/.eslintrc.base.json +0 -23
- package/playgrounds/ts/.eslintrc.json +0 -191
- package/playgrounds/ts/.vscode/settings.json +0 -12
- package/playgrounds/ts/package-lock.json +0 -2687
- package/playgrounds/ts/package.json +0 -11
- package/playgrounds/ts/test copy.ts +0 -4
- package/playgrounds/ts/test.ipynb +0 -49
- package/playgrounds/ts/test.ts +0 -4
- package/playgrounds/ts/test.tsx +0 -14
- package/playgrounds/ts/tsconfig.json +0 -100
- package/server/agents.md +0 -9
- package/server/package-lock.json +0 -93
- package/server/package.json +0 -32
- package/server/src/diff.ts +0 -1079
- package/server/src/eslint.ts +0 -1471
- package/server/src/eslintServer.ts +0 -865
- package/server/src/is.ts +0 -18
- package/server/src/languageDefaults.ts +0 -40
- package/server/src/linkedMap.ts +0 -448
- package/server/src/paths.ts +0 -128
- package/server/src/thenable.d.ts +0 -5
- package/server/tsconfig.json +0 -21
- package/server/webpack.config.js +0 -25
- package/shared.webpack.config.js +0 -59
- package/tsconfig.base.json +0 -9
- package/tsconfig.json +0 -21
package/client/src/client.ts
DELETED
|
@@ -1,992 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
/* --------------------------------------------------------------------------------------------
|
|
3
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4
|
-
* Licensed under the MIT License. See License.txt in the project root for license information.
|
|
5
|
-
* ------------------------------------------------------------------------------------------ */
|
|
6
|
-
|
|
7
|
-
import * as path from 'path';
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
workspace as Workspace, window as Window, languages as Languages, Uri, TextDocument, CodeActionContext, Diagnostic,
|
|
11
|
-
Command, CodeAction, MessageItem, ConfigurationTarget, env as Env, CodeActionKind, WorkspaceConfiguration, NotebookCell, commands,
|
|
12
|
-
ExtensionContext, LanguageStatusItem, LanguageStatusSeverity, DocumentFilter as VDocumentFilter
|
|
13
|
-
} from 'vscode';
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
LanguageClient, LanguageClientOptions, TransportKind, ErrorHandler, CloseAction, RevealOutputChannelOn, ServerOptions,
|
|
17
|
-
DidCloseTextDocumentNotification, DidOpenTextDocumentNotification, State, VersionedTextDocumentIdentifier, ExecuteCommandParams,
|
|
18
|
-
ExecuteCommandRequest, ConfigurationParams, NotebookDocumentSyncRegistrationType, DiagnosticPullMode, DocumentDiagnosticRequest
|
|
19
|
-
} from 'vscode-languageclient/node';
|
|
20
|
-
|
|
21
|
-
import { LegacyDirectoryItem, Migration, PatternItem, ValidateItem } from './settings';
|
|
22
|
-
import { ExitCalled, NoConfigRequest, NoESLintLibraryRequest, OpenESLintDocRequest, ProbeFailedRequest, ShowOutputChannel, Status, StatusNotification, StatusParams } from './shared/customMessages';
|
|
23
|
-
import { CodeActionSettings, CodeActionsOnSaveMode, CodeActionsOnSaveOptions, CodeActionsOnSaveRules, ConfigurationSettings, DirectoryItem, ESLintOptions, ESLintSeverity, ModeItem, PackageManagers, RuleCustomization, RunValues, Validate } from './shared/settings';
|
|
24
|
-
import { convert2RegExp, Is, Semaphore, toOSPath, toPosixPath } from './node-utils';
|
|
25
|
-
import { pickFolder } from './vscode-utils';
|
|
26
|
-
|
|
27
|
-
export class Validator {
|
|
28
|
-
|
|
29
|
-
private readonly probeFailed: Set<string> = new Set();
|
|
30
|
-
|
|
31
|
-
public clear(): void {
|
|
32
|
-
this.probeFailed.clear();
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
public add(uri: Uri): void {
|
|
36
|
-
this.probeFailed.add(uri.toString());
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
public check(textDocument: TextDocument): Validate {
|
|
40
|
-
const config = Workspace.getConfiguration('eslint', textDocument.uri);
|
|
41
|
-
|
|
42
|
-
if (!config.get<boolean>('enable', true)) {
|
|
43
|
-
return Validate.off;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (textDocument.uri.scheme === 'untitled' && config.get<boolean>('ignoreUntitled', false)) {
|
|
47
|
-
return Validate.off;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const languageId = textDocument.languageId;
|
|
51
|
-
const validate = config.get<((ValidateItem | string)[]) | null>('validate', null);
|
|
52
|
-
if (Array.isArray(validate)) {
|
|
53
|
-
for (const item of validate) {
|
|
54
|
-
if (Is.string(item) && item === languageId) {
|
|
55
|
-
return Validate.on;
|
|
56
|
-
} else if (ValidateItem.is(item) && item.language === languageId) {
|
|
57
|
-
return Validate.on;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
return Validate.off;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
if (this.probeFailed.has(textDocument.uri.toString())) {
|
|
64
|
-
return Validate.off;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const probe: string[] | undefined = config.get<string[]>('probe');
|
|
68
|
-
if (Array.isArray(probe)) {
|
|
69
|
-
for (const item of probe) {
|
|
70
|
-
if (item === languageId) {
|
|
71
|
-
return Validate.probe;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
return Validate.off;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
type NoESLintState = {
|
|
81
|
-
global?: boolean;
|
|
82
|
-
workspaces?: { [key: string]: boolean };
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export namespace ESLintClient {
|
|
86
|
-
|
|
87
|
-
function migrationFailed(client: LanguageClient, error: any): void {
|
|
88
|
-
client.error(error.message ?? 'Unknown error', error);
|
|
89
|
-
void Window.showErrorMessage('ESLint settings migration failed. Please see the ESLint output channel for further details', 'Open Channel').then((selected) => {
|
|
90
|
-
if (selected === undefined) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
client.outputChannel.show();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export async function migrateSettings(client: LanguageClient): Promise<void> {
|
|
99
|
-
const folders = Workspace.workspaceFolders;
|
|
100
|
-
if (folders === undefined) {
|
|
101
|
-
void Window.showErrorMessage('ESLint settings can only be converted if VS Code is opened on a workspace folder.');
|
|
102
|
-
return;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const folder = await pickFolder(folders, 'Pick a folder to convert its settings');
|
|
106
|
-
if (folder === undefined) {
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const migration = new Migration(folder.uri);
|
|
110
|
-
migration.record();
|
|
111
|
-
if (migration.needsUpdate()) {
|
|
112
|
-
try {
|
|
113
|
-
await migration.update();
|
|
114
|
-
} catch (error) {
|
|
115
|
-
migrationFailed(client, error);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
interface TimeBudget {
|
|
121
|
-
warn: number;
|
|
122
|
-
error: number;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
type PerformanceStatus = {
|
|
126
|
-
firstReport: boolean;
|
|
127
|
-
validationTime: number;
|
|
128
|
-
fixTime: number;
|
|
129
|
-
reported: number;
|
|
130
|
-
acknowledged: boolean;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
namespace PerformanceStatus {
|
|
134
|
-
export const defaultValue: PerformanceStatus = { firstReport: true, validationTime: 0, fixTime: 0, reported: 0, acknowledged: false };
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function create(context: ExtensionContext, validator: Validator): [LanguageClient, () => void] {
|
|
138
|
-
|
|
139
|
-
// Filters for client options
|
|
140
|
-
const packageJsonFilter: VDocumentFilter = { scheme: 'file', pattern: '**/package.json' };
|
|
141
|
-
const configFileFilter: VDocumentFilter = { scheme: 'file', pattern: '**/{.eslintr{c.js,c.yaml,c.yml,c,c.json},eslint.confi{g.js,g.mjs,g.cjs}}' };
|
|
142
|
-
const supportedQuickFixKinds: Set<string> = new Set([CodeActionKind.Source.value, CodeActionKind.SourceFixAll.value, `${CodeActionKind.SourceFixAll.value}.eslint`, CodeActionKind.QuickFix.value]);
|
|
143
|
-
|
|
144
|
-
// A map of documents synced to the server
|
|
145
|
-
const syncedDocuments: Map<string, TextDocument> = new Map();
|
|
146
|
-
// The actual ESLint client
|
|
147
|
-
const client: LanguageClient = new LanguageClient('ESLint', createServerOptions(context.extensionUri), createClientOptions());
|
|
148
|
-
|
|
149
|
-
// The default error handler.
|
|
150
|
-
const defaultErrorHandler: ErrorHandler = client.createDefaultErrorHandler();
|
|
151
|
-
// Whether the server call process.exit() which is intercepted and reported to
|
|
152
|
-
// the client
|
|
153
|
-
let serverCalledProcessExit: boolean = false;
|
|
154
|
-
|
|
155
|
-
// A semaphore to ensure we are only running one migration at a time
|
|
156
|
-
const migrationSemaphore: Semaphore<void> = new Semaphore<void>(1);
|
|
157
|
-
// The actual migration code if any.
|
|
158
|
-
let migration: Migration | undefined;
|
|
159
|
-
// Whether migration should happen now
|
|
160
|
-
let notNow: boolean = false;
|
|
161
|
-
|
|
162
|
-
// The client's status bar item.
|
|
163
|
-
const languageStatus: LanguageStatusItem = Languages.createLanguageStatusItem('eslint.languageStatusItem', []);
|
|
164
|
-
let serverRunning: boolean | undefined;
|
|
165
|
-
|
|
166
|
-
const starting = 'ESLint server is starting.';
|
|
167
|
-
const running = 'ESLint server is running.';
|
|
168
|
-
const stopped = 'ESLint server stopped.';
|
|
169
|
-
languageStatus.name = 'ESLint';
|
|
170
|
-
languageStatus.text = 'ESLint';
|
|
171
|
-
languageStatus.command = { title: 'Open ESLint Output', command: 'eslint.showOutputChannel' };
|
|
172
|
-
type StatusInfo = Omit<Omit<StatusParams, 'uri'>, 'validationTime'> & {
|
|
173
|
-
};
|
|
174
|
-
const documentStatus: Map<string, StatusInfo> = new Map();
|
|
175
|
-
const performanceStatus: Map<string, PerformanceStatus> = new Map();
|
|
176
|
-
|
|
177
|
-
// If the workspace configuration changes we need to update the synced documents since the
|
|
178
|
-
// list of probe language type can change.
|
|
179
|
-
context.subscriptions.push(Workspace.onDidChangeConfiguration(() => {
|
|
180
|
-
validator.clear();
|
|
181
|
-
for (const textDocument of syncedDocuments.values()) {
|
|
182
|
-
if (validator.check(textDocument) === Validate.off) {
|
|
183
|
-
const provider = client.getFeature(DidCloseTextDocumentNotification.method).getProvider(textDocument);
|
|
184
|
-
provider?.send(textDocument).catch((error) => client.error(`Sending close notification failed.`, error));
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
for (const textDocument of Workspace.textDocuments) {
|
|
188
|
-
if (!syncedDocuments.has(textDocument.uri.toString()) && validator.check(textDocument) !== Validate.off) {
|
|
189
|
-
const provider = client.getFeature(DidOpenTextDocumentNotification.method).getProvider(textDocument);
|
|
190
|
-
provider?.send(textDocument).catch((error) => client.error(`Sending open notification failed.`, error));
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}));
|
|
194
|
-
|
|
195
|
-
client.onNotification(ShowOutputChannel.type, () => {
|
|
196
|
-
client.outputChannel.show();
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
client.onNotification(StatusNotification.type, (params) => {
|
|
200
|
-
updateDocumentStatus(params);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
client.onNotification(ExitCalled.type, (params) => {
|
|
204
|
-
serverCalledProcessExit = true;
|
|
205
|
-
client.error(`Server process exited with code ${params[0]}. This usually indicates a misconfigured ESLint setup.`, params[1]);
|
|
206
|
-
void Window.showErrorMessage(`ESLint server shut down itself. See 'ESLint' output channel for details.`, { title: 'Open Output', id: 1}).then((value) => {
|
|
207
|
-
if (value !== undefined && value.id === 1) {
|
|
208
|
-
client.outputChannel.show();
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
});
|
|
212
|
-
|
|
213
|
-
client.onRequest(NoConfigRequest.type, (params) => {
|
|
214
|
-
const document = Uri.parse(params.document.uri);
|
|
215
|
-
const workspaceFolder = Workspace.getWorkspaceFolder(document);
|
|
216
|
-
const fileLocation = document.fsPath;
|
|
217
|
-
if (workspaceFolder) {
|
|
218
|
-
client.warn([
|
|
219
|
-
'',
|
|
220
|
-
`No ESLint configuration (e.g .eslintrc) found for file: ${fileLocation}`,
|
|
221
|
-
`File will not be validated. Consider running 'eslint --init' in the workspace folder ${workspaceFolder.name}`,
|
|
222
|
-
`Alternatively you can disable ESLint by executing the 'Disable ESLint' command.`
|
|
223
|
-
].join('\n'));
|
|
224
|
-
} else {
|
|
225
|
-
client.warn([
|
|
226
|
-
'',
|
|
227
|
-
`No ESLint configuration (e.g .eslintrc) found for file: ${fileLocation}`,
|
|
228
|
-
`File will not be validated. Alternatively you can disable ESLint by executing the 'Disable ESLint' command.`
|
|
229
|
-
].join('\n'));
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
updateDocumentStatus({ uri: params.document.uri, state: Status.error });
|
|
233
|
-
return {};
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
client.onRequest(NoESLintLibraryRequest.type, async (params) => {
|
|
237
|
-
const key = 'noESLintMessageShown';
|
|
238
|
-
const state = context.globalState.get<NoESLintState>(key, {});
|
|
239
|
-
|
|
240
|
-
const uri: Uri = Uri.parse(params.source.uri);
|
|
241
|
-
const workspaceFolder = Workspace.getWorkspaceFolder(uri);
|
|
242
|
-
const packageManager = await getPackageManager(uri);
|
|
243
|
-
const localInstall = {
|
|
244
|
-
npm: 'npm install eslint',
|
|
245
|
-
pnpm: 'pnpm install eslint',
|
|
246
|
-
yarn: 'yarn add eslint',
|
|
247
|
-
};
|
|
248
|
-
const globalInstall = {
|
|
249
|
-
npm: 'npm install -g eslint',
|
|
250
|
-
pnpm: 'pnpm install -g eslint',
|
|
251
|
-
yarn: 'yarn global add eslint'
|
|
252
|
-
};
|
|
253
|
-
interface ButtonItem extends MessageItem {
|
|
254
|
-
id: number;
|
|
255
|
-
}
|
|
256
|
-
const outputItem: ButtonItem = {
|
|
257
|
-
title: 'Go to output',
|
|
258
|
-
id: 1
|
|
259
|
-
};
|
|
260
|
-
if (workspaceFolder) {
|
|
261
|
-
client.info([
|
|
262
|
-
'',
|
|
263
|
-
`Failed to load the ESLint library for the document ${uri.fsPath}`,
|
|
264
|
-
'',
|
|
265
|
-
`To use ESLint please install eslint by running ${localInstall[packageManager]} in the workspace folder ${workspaceFolder.name}`,
|
|
266
|
-
`or globally using '${globalInstall[packageManager]}'. You need to reopen the workspace after installing eslint.`,
|
|
267
|
-
'',
|
|
268
|
-
`Alternatively you can disable ESLint for the workspace folder ${workspaceFolder.name} by executing the 'Disable ESLint' command.`
|
|
269
|
-
].filter((str => (str !== null))).join('\n'));
|
|
270
|
-
|
|
271
|
-
if (state.workspaces === undefined) {
|
|
272
|
-
state.workspaces = {};
|
|
273
|
-
}
|
|
274
|
-
if (!state.workspaces[workspaceFolder.uri.toString()]) {
|
|
275
|
-
state.workspaces[workspaceFolder.uri.toString()] = true;
|
|
276
|
-
void context.globalState.update(key, state);
|
|
277
|
-
void Window.showInformationMessage(`Failed to load the ESLint library for the document ${uri.fsPath}. See the output for more information.`, outputItem).then((item) => {
|
|
278
|
-
if (item && item.id === 1) {
|
|
279
|
-
client.outputChannel.show(true);
|
|
280
|
-
}
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
} else {
|
|
284
|
-
client.info([
|
|
285
|
-
`Failed to load the ESLint library for the document ${uri.fsPath}`,
|
|
286
|
-
`To use ESLint for single JavaScript file install eslint globally using '${globalInstall[packageManager]}'.`,
|
|
287
|
-
'You need to reopen VS Code after installing eslint.',
|
|
288
|
-
].filter((str => (str !== null))).join('\n'));
|
|
289
|
-
|
|
290
|
-
if (!state.global) {
|
|
291
|
-
state.global = true;
|
|
292
|
-
void context.globalState.update(key, state);
|
|
293
|
-
void Window.showInformationMessage(`Failed to load the ESLint library for the document ${uri.fsPath}. See the output for more information.`, outputItem).then((item) => {
|
|
294
|
-
if (item && item.id === 1) {
|
|
295
|
-
client.outputChannel.show(true);
|
|
296
|
-
}
|
|
297
|
-
});
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
return {};
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
client.onRequest(OpenESLintDocRequest.type, async (params) => {
|
|
304
|
-
await commands.executeCommand('vscode.open', Uri.parse(params.url));
|
|
305
|
-
return {};
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
client.onRequest(ProbeFailedRequest.type, (params) => {
|
|
309
|
-
const uri = client.protocol2CodeConverter.asUri(params.textDocument.uri);
|
|
310
|
-
validator.add(uri);
|
|
311
|
-
const closeFeature = client.getFeature(DidCloseTextDocumentNotification.method);
|
|
312
|
-
const diagnosticsFeature = client.getFeature(DocumentDiagnosticRequest.method);
|
|
313
|
-
for (const document of Workspace.textDocuments) {
|
|
314
|
-
if (document.uri.toString() === uri.toString()) {
|
|
315
|
-
closeFeature.getProvider(document)?.send(document).catch((error) => client.error(`Sending close notification failed`, error));
|
|
316
|
-
diagnosticsFeature?.getProvider(document)?.forget(document);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
const notebookFeature = client.getFeature(NotebookDocumentSyncRegistrationType.method);
|
|
322
|
-
if (notebookFeature !== undefined) {
|
|
323
|
-
notebookFeature.register({
|
|
324
|
-
id: String(Date.now()),
|
|
325
|
-
registerOptions: {
|
|
326
|
-
notebookSelector: [{
|
|
327
|
-
notebook: { scheme: 'file' },
|
|
328
|
-
// We dynamically filter using the filterCells callback.
|
|
329
|
-
// To force the filtering match all cells for now.
|
|
330
|
-
// See also https://github.com/microsoft/vscode-languageserver-node/issues/1017
|
|
331
|
-
cells: [ { language: '*' } ]
|
|
332
|
-
}]
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
client.onDidChangeState((event) => {
|
|
338
|
-
if (event.newState === State.Starting) {
|
|
339
|
-
client.info(starting);
|
|
340
|
-
serverRunning = undefined;
|
|
341
|
-
} else if (event.newState === State.Running) {
|
|
342
|
-
client.info(running);
|
|
343
|
-
serverRunning = true;
|
|
344
|
-
} else {
|
|
345
|
-
client.info(stopped);
|
|
346
|
-
serverRunning = false;
|
|
347
|
-
}
|
|
348
|
-
updateStatusBar(undefined);
|
|
349
|
-
});
|
|
350
|
-
|
|
351
|
-
context.subscriptions.push(
|
|
352
|
-
Window.onDidChangeActiveTextEditor(() => {
|
|
353
|
-
updateStatusBar(undefined);
|
|
354
|
-
}),
|
|
355
|
-
Workspace.onDidCloseTextDocument((document) => {
|
|
356
|
-
const uri = document.uri.toString();
|
|
357
|
-
documentStatus.delete(uri);
|
|
358
|
-
updateLanguageStatusSelector();
|
|
359
|
-
updateStatusBar(undefined);
|
|
360
|
-
}),
|
|
361
|
-
commands.registerCommand('eslint.executeAutofix', async () => {
|
|
362
|
-
const textEditor = Window.activeTextEditor;
|
|
363
|
-
if (!textEditor) {
|
|
364
|
-
return;
|
|
365
|
-
}
|
|
366
|
-
const textDocument: VersionedTextDocumentIdentifier = {
|
|
367
|
-
uri: textEditor.document.uri.toString(),
|
|
368
|
-
version: textEditor.document.version
|
|
369
|
-
};
|
|
370
|
-
const params: ExecuteCommandParams = {
|
|
371
|
-
command: 'eslint.applyAllFixes',
|
|
372
|
-
arguments: [textDocument]
|
|
373
|
-
};
|
|
374
|
-
await client.start();
|
|
375
|
-
client.sendRequest(ExecuteCommandRequest.type, params).then(undefined, () => {
|
|
376
|
-
void Window.showErrorMessage('Failed to apply ESLint fixes to the document. Please consider opening an issue with steps to reproduce.');
|
|
377
|
-
});
|
|
378
|
-
})
|
|
379
|
-
);
|
|
380
|
-
|
|
381
|
-
return [client, acknowledgePerformanceStatus];
|
|
382
|
-
|
|
383
|
-
function getCurrentServerWorkingDirectory(): string {
|
|
384
|
-
if (!Workspace.isTrusted) {
|
|
385
|
-
return process.cwd();
|
|
386
|
-
}
|
|
387
|
-
const workspaceFolders = Workspace.workspaceFolders;
|
|
388
|
-
if (workspaceFolders === undefined || workspaceFolders.length !== 1) {
|
|
389
|
-
return process.cwd();
|
|
390
|
-
}
|
|
391
|
-
const uri = workspaceFolders[0].uri;
|
|
392
|
-
if (uri.scheme !== 'file') {
|
|
393
|
-
return process.cwd();
|
|
394
|
-
}
|
|
395
|
-
return uri.fsPath;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
function createServerOptions(extensionUri: Uri): ServerOptions {
|
|
399
|
-
const serverModule = Uri.joinPath(extensionUri, 'server', 'out', 'eslintServer.js').fsPath;
|
|
400
|
-
const eslintConfig = Workspace.getConfiguration('eslint');
|
|
401
|
-
const debug = sanitize(eslintConfig.get<boolean>('debug', false) ?? false, 'boolean', false);
|
|
402
|
-
const runtime = sanitize(eslintConfig.get<string | null>('runtime', null) ?? undefined, 'string', undefined);
|
|
403
|
-
const execArgv = sanitize(eslintConfig.get<string[] | null>('execArgv', null) ?? undefined, 'string', undefined);
|
|
404
|
-
const nodeEnv = sanitize(eslintConfig.get<string | null>('nodeEnv', null) ?? undefined, 'string', undefined);
|
|
405
|
-
|
|
406
|
-
let env: { [key: string]: string | number | boolean } | undefined;
|
|
407
|
-
if (debug) {
|
|
408
|
-
env = env || {};
|
|
409
|
-
env.DEBUG = 'eslint:*,-eslint:code-path,eslintrc:*';
|
|
410
|
-
}
|
|
411
|
-
if (nodeEnv !== undefined) {
|
|
412
|
-
env = env || {};
|
|
413
|
-
env.NODE_ENV = nodeEnv;
|
|
414
|
-
}
|
|
415
|
-
const cwd = getCurrentServerWorkingDirectory();
|
|
416
|
-
const debugArgv = ['--nolazy', '--inspect=6011'];
|
|
417
|
-
const result: ServerOptions = {
|
|
418
|
-
run: { module: serverModule, transport: TransportKind.ipc, runtime, options: { execArgv, cwd, env } },
|
|
419
|
-
debug: { module: serverModule, transport: TransportKind.ipc, runtime, options: { execArgv: execArgv !== undefined ? execArgv.concat(debugArgv) : debugArgv, cwd, env } }
|
|
420
|
-
};
|
|
421
|
-
return result;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
function sanitize<T, D>(value: T, type: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined', def: D): T | D {
|
|
425
|
-
if (Array.isArray(value)) {
|
|
426
|
-
return value.filter(item => typeof item === type) as unknown as T;
|
|
427
|
-
} else if (typeof value !== type) {
|
|
428
|
-
return def;
|
|
429
|
-
}
|
|
430
|
-
return value;
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
function createClientOptions(): LanguageClientOptions {
|
|
434
|
-
const clientOptions: LanguageClientOptions = {
|
|
435
|
-
documentSelector: [{ scheme: 'file' }, { scheme: 'untitled' }],
|
|
436
|
-
revealOutputChannelOn: RevealOutputChannelOn.Never,
|
|
437
|
-
initializationOptions: {
|
|
438
|
-
},
|
|
439
|
-
progressOnInitialization: true,
|
|
440
|
-
synchronize: {
|
|
441
|
-
fileEvents: [
|
|
442
|
-
Workspace.createFileSystemWatcher('**/.eslintr{c.js,c.cjs,c.yaml,c.yml,c,c.json}'),
|
|
443
|
-
Workspace.createFileSystemWatcher('**/eslint.config.{js,mjs,cjs,ts,mts,cts}'),
|
|
444
|
-
Workspace.createFileSystemWatcher('**/.eslintignore'),
|
|
445
|
-
Workspace.createFileSystemWatcher('**/package.json')
|
|
446
|
-
]
|
|
447
|
-
},
|
|
448
|
-
initializationFailedHandler: (error) => {
|
|
449
|
-
client.error('Server initialization failed.', error);
|
|
450
|
-
client.outputChannel.show(true);
|
|
451
|
-
return false;
|
|
452
|
-
},
|
|
453
|
-
errorHandler: {
|
|
454
|
-
error: (error, message, count) => {
|
|
455
|
-
return defaultErrorHandler.error(error, message, count);
|
|
456
|
-
},
|
|
457
|
-
closed: () => {
|
|
458
|
-
if (serverCalledProcessExit) {
|
|
459
|
-
return { action: CloseAction.DoNotRestart };
|
|
460
|
-
}
|
|
461
|
-
return defaultErrorHandler.closed();
|
|
462
|
-
}
|
|
463
|
-
},
|
|
464
|
-
diagnosticPullOptions: {
|
|
465
|
-
onChange: true,
|
|
466
|
-
onSave: true,
|
|
467
|
-
onFocus: true,
|
|
468
|
-
filter: (document, mode) => {
|
|
469
|
-
const config = Workspace.getConfiguration('eslint', document);
|
|
470
|
-
const run = config.get<RunValues>('run', 'onType');
|
|
471
|
-
if (mode === DiagnosticPullMode.onType && run !== 'onType') {
|
|
472
|
-
return true;
|
|
473
|
-
} else if (mode === DiagnosticPullMode.onSave && run !== 'onSave') {
|
|
474
|
-
return true;
|
|
475
|
-
}
|
|
476
|
-
return validator.check(document) === Validate.off;
|
|
477
|
-
},
|
|
478
|
-
onTabs: false
|
|
479
|
-
},
|
|
480
|
-
middleware: {
|
|
481
|
-
didOpen: async (document, next) => {
|
|
482
|
-
if (Languages.match(packageJsonFilter, document) || Languages.match(configFileFilter, document) || validator.check(document) !== Validate.off) {
|
|
483
|
-
const result = next(document);
|
|
484
|
-
syncedDocuments.set(document.uri.toString(), document);
|
|
485
|
-
|
|
486
|
-
return result;
|
|
487
|
-
}
|
|
488
|
-
},
|
|
489
|
-
didChange: async (event, next) => {
|
|
490
|
-
if (syncedDocuments.has(event.document.uri.toString())) {
|
|
491
|
-
return next(event);
|
|
492
|
-
}
|
|
493
|
-
},
|
|
494
|
-
willSave: async (event, next) => {
|
|
495
|
-
if (syncedDocuments.has(event.document.uri.toString())) {
|
|
496
|
-
return next(event);
|
|
497
|
-
}
|
|
498
|
-
},
|
|
499
|
-
willSaveWaitUntil: (event, next) => {
|
|
500
|
-
if (syncedDocuments.has(event.document.uri.toString())) {
|
|
501
|
-
return next(event);
|
|
502
|
-
} else {
|
|
503
|
-
return Promise.resolve([]);
|
|
504
|
-
}
|
|
505
|
-
},
|
|
506
|
-
didSave: async (document, next) => {
|
|
507
|
-
if (syncedDocuments.has(document.uri.toString())) {
|
|
508
|
-
return next(document);
|
|
509
|
-
}
|
|
510
|
-
},
|
|
511
|
-
didClose: async (document, next) => {
|
|
512
|
-
const uri = document.uri.toString();
|
|
513
|
-
if (syncedDocuments.has(uri)) {
|
|
514
|
-
syncedDocuments.delete(uri);
|
|
515
|
-
return next(document);
|
|
516
|
-
}
|
|
517
|
-
},
|
|
518
|
-
notebooks: {
|
|
519
|
-
didOpen: (notebookDocument, cells, next) => {
|
|
520
|
-
const result = next(notebookDocument, cells);
|
|
521
|
-
for (const cell of cells) {
|
|
522
|
-
syncedDocuments.set(cell.document.uri.toString(), cell.document);
|
|
523
|
-
}
|
|
524
|
-
return result;
|
|
525
|
-
},
|
|
526
|
-
didChange: (event, next) => {
|
|
527
|
-
if (event.cells?.structure?.didOpen !== undefined) {
|
|
528
|
-
for (const open of event.cells.structure.didOpen) {
|
|
529
|
-
syncedDocuments.set(open.document.uri.toString(), open.document);
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
if (event.cells?.structure?.didClose !== undefined) {
|
|
533
|
-
for (const closed of event.cells.structure.didClose) {
|
|
534
|
-
syncedDocuments.delete(closed.document.uri.toString());
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
return next(event);
|
|
538
|
-
},
|
|
539
|
-
didClose: (document, cells, next) => {
|
|
540
|
-
for (const cell of cells) {
|
|
541
|
-
const key = cell.document.uri.toString();
|
|
542
|
-
syncedDocuments.delete(key);
|
|
543
|
-
}
|
|
544
|
-
return next(document, cells);
|
|
545
|
-
}
|
|
546
|
-
},
|
|
547
|
-
provideCodeActions: async (document, range, context, token, next): Promise<(Command | CodeAction)[] | null | undefined> => {
|
|
548
|
-
if (!syncedDocuments.has(document.uri.toString())) {
|
|
549
|
-
return [];
|
|
550
|
-
}
|
|
551
|
-
if (context.only !== undefined && !supportedQuickFixKinds.has(context.only.value)) {
|
|
552
|
-
return [];
|
|
553
|
-
}
|
|
554
|
-
if (context.only === undefined && (!context.diagnostics || context.diagnostics.length === 0)) {
|
|
555
|
-
return [];
|
|
556
|
-
}
|
|
557
|
-
const eslintDiagnostics: Diagnostic[] = [];
|
|
558
|
-
for (const diagnostic of context.diagnostics) {
|
|
559
|
-
if (diagnostic.source === 'eslint') {
|
|
560
|
-
eslintDiagnostics.push(diagnostic);
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
if (context.only === undefined && eslintDiagnostics.length === 0) {
|
|
564
|
-
return [];
|
|
565
|
-
}
|
|
566
|
-
const newContext: CodeActionContext = Object.assign({}, context, { diagnostics: eslintDiagnostics });
|
|
567
|
-
const start = Date.now();
|
|
568
|
-
const result = await next(document, range, newContext, token);
|
|
569
|
-
if (context.only?.value.startsWith('source.fixAll')) {
|
|
570
|
-
let performanceInfo = performanceStatus.get(document.languageId);
|
|
571
|
-
if (performanceInfo === undefined) {
|
|
572
|
-
performanceInfo = PerformanceStatus.defaultValue;
|
|
573
|
-
performanceStatus.set(document.languageId, performanceInfo);
|
|
574
|
-
} else {
|
|
575
|
-
performanceInfo.firstReport = false;
|
|
576
|
-
}
|
|
577
|
-
performanceInfo.fixTime = Date.now() - start;
|
|
578
|
-
updateStatusBar(document);
|
|
579
|
-
}
|
|
580
|
-
return result;
|
|
581
|
-
},
|
|
582
|
-
workspace: {
|
|
583
|
-
didChangeWatchedFile: (event, next) => {
|
|
584
|
-
validator.clear();
|
|
585
|
-
return next(event);
|
|
586
|
-
},
|
|
587
|
-
didChangeConfiguration: async (sections, next) => {
|
|
588
|
-
if (migration !== undefined && (sections === undefined || sections.length === 0)) {
|
|
589
|
-
migration.captureDidChangeSetting(() => {
|
|
590
|
-
return next(sections);
|
|
591
|
-
});
|
|
592
|
-
} else {
|
|
593
|
-
return next(sections);
|
|
594
|
-
}
|
|
595
|
-
},
|
|
596
|
-
configuration: (params) => {
|
|
597
|
-
return readConfiguration(params);
|
|
598
|
-
}
|
|
599
|
-
}
|
|
600
|
-
},
|
|
601
|
-
notebookDocumentOptions: {
|
|
602
|
-
filterCells: (_notebookDocument, cells) => {
|
|
603
|
-
const result: NotebookCell[] = [];
|
|
604
|
-
for (const cell of cells) {
|
|
605
|
-
const document = cell.document;
|
|
606
|
-
if (Languages.match(packageJsonFilter, document) || Languages.match(configFileFilter, document) || validator.check(document) !== Validate.off) {
|
|
607
|
-
result.push(cell);
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
return result;
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
};
|
|
614
|
-
return clientOptions;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
async function getPackageManager(uri: Uri) {
|
|
618
|
-
const userProvidedPackageManager:PackageManagers = Workspace.getConfiguration('eslint', uri).get('packageManager', 'npm');
|
|
619
|
-
const detectedPackageManager = await commands.executeCommand<PackageManagers>('npm.packageManager');
|
|
620
|
-
|
|
621
|
-
if (userProvidedPackageManager === detectedPackageManager) {
|
|
622
|
-
return detectedPackageManager;
|
|
623
|
-
}
|
|
624
|
-
client.warn(`Detected package manager(${detectedPackageManager}) differs from the one in the deprecated packageManager setting(${userProvidedPackageManager}). We will honor this setting until it is removed.`, {}, true);
|
|
625
|
-
return userProvidedPackageManager;
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
async function readConfiguration(params: ConfigurationParams): Promise<(ConfigurationSettings | null)[]> {
|
|
629
|
-
if (params.items === undefined) {
|
|
630
|
-
return [];
|
|
631
|
-
}
|
|
632
|
-
const result: (ConfigurationSettings | null)[] = [];
|
|
633
|
-
for (const item of params.items) {
|
|
634
|
-
if (item.section || !item.scopeUri) {
|
|
635
|
-
result.push(null);
|
|
636
|
-
continue;
|
|
637
|
-
}
|
|
638
|
-
const resource = client.protocol2CodeConverter.asUri(item.scopeUri);
|
|
639
|
-
const textDocument = getTextDocument(resource);
|
|
640
|
-
const config = Workspace.getConfiguration('eslint', textDocument ?? resource);
|
|
641
|
-
const workspaceFolder = resource.scheme === 'untitled'
|
|
642
|
-
? Workspace.workspaceFolders?.[0]
|
|
643
|
-
: Workspace.getWorkspaceFolder(resource);
|
|
644
|
-
await migrationSemaphore.lock(async () => {
|
|
645
|
-
const globalMigration = Workspace.getConfiguration('eslint').get('migration.2_x', 'on');
|
|
646
|
-
if (notNow === false && globalMigration === 'on') {
|
|
647
|
-
try {
|
|
648
|
-
migration = new Migration(resource);
|
|
649
|
-
migration.record();
|
|
650
|
-
interface Item extends MessageItem {
|
|
651
|
-
id: 'yes' | 'no' | 'readme' | 'global' | 'local';
|
|
652
|
-
}
|
|
653
|
-
if (migration.needsUpdate()) {
|
|
654
|
-
const folder = workspaceFolder?.name;
|
|
655
|
-
const file = path.basename(resource.fsPath);
|
|
656
|
-
const selected = await Window.showInformationMessage<Item>(
|
|
657
|
-
[
|
|
658
|
-
`The ESLint 'autoFixOnSave' setting needs to be migrated to the new 'editor.codeActionsOnSave' setting`,
|
|
659
|
-
folder !== undefined ? `for the workspace folder: ${folder}.` : `for the file: ${file}.`,
|
|
660
|
-
`For compatibility reasons the 'autoFixOnSave' remains and needs to be removed manually.`,
|
|
661
|
-
`Do you want to migrate the setting?`
|
|
662
|
-
].join(' '),
|
|
663
|
-
{ modal: true},
|
|
664
|
-
{ id: 'yes', title: 'Yes'},
|
|
665
|
-
{ id: 'global', title: 'Never migrate Settings' },
|
|
666
|
-
{ id: 'readme', title: 'Open Readme' },
|
|
667
|
-
{ id: 'no', title: 'Not now', isCloseAffordance: true }
|
|
668
|
-
);
|
|
669
|
-
if (selected !== undefined) {
|
|
670
|
-
if (selected.id === 'yes') {
|
|
671
|
-
try {
|
|
672
|
-
await migration.update();
|
|
673
|
-
} catch (error) {
|
|
674
|
-
migrationFailed(client, error);
|
|
675
|
-
}
|
|
676
|
-
} else if (selected.id === 'no') {
|
|
677
|
-
notNow = true;
|
|
678
|
-
} else if (selected.id === 'global') {
|
|
679
|
-
await config.update('migration.2_x', 'off', ConfigurationTarget.Global);
|
|
680
|
-
} else if (selected.id === 'readme') {
|
|
681
|
-
notNow = true;
|
|
682
|
-
void Env.openExternal(Uri.parse('https://github.com/microsoft/vscode-eslint#settings-migration'));
|
|
683
|
-
}
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
} finally {
|
|
687
|
-
migration = undefined;
|
|
688
|
-
}
|
|
689
|
-
}
|
|
690
|
-
});
|
|
691
|
-
const useFlatConfig = config.get<boolean | null>('useFlatConfig', null);
|
|
692
|
-
const settings: ConfigurationSettings = {
|
|
693
|
-
validate: Validate.off,
|
|
694
|
-
packageManager: config.get<PackageManagers>('packageManager', 'npm'),
|
|
695
|
-
useESLintClass: config.get<boolean>('useESLintClass', false),
|
|
696
|
-
useFlatConfig: useFlatConfig === null ? undefined : useFlatConfig,
|
|
697
|
-
useRealpaths: config.get<boolean>('useRealpaths', false),
|
|
698
|
-
experimental: {
|
|
699
|
-
useFlatConfig: config.get<boolean>('experimental.useFlatConfig', false),
|
|
700
|
-
},
|
|
701
|
-
codeActionOnSave: {
|
|
702
|
-
mode: CodeActionsOnSaveMode.all
|
|
703
|
-
},
|
|
704
|
-
format: false,
|
|
705
|
-
quiet: config.get<boolean>('quiet', false),
|
|
706
|
-
onIgnoredFiles: ESLintSeverity.from(config.get<string>('onIgnoredFiles', ESLintSeverity.off)),
|
|
707
|
-
options: config.get<ESLintOptions>('options', {}),
|
|
708
|
-
rulesCustomizations: getRuleCustomizations(config, resource),
|
|
709
|
-
run: config.get<RunValues>('run', 'onType'),
|
|
710
|
-
problems: {
|
|
711
|
-
shortenToSingleLine: config.get<boolean>('problems.shortenToSingleLine', false),
|
|
712
|
-
},
|
|
713
|
-
nodePath: config.get<string | undefined>('nodePath', undefined) ?? null,
|
|
714
|
-
workingDirectory: undefined,
|
|
715
|
-
workspaceFolder: undefined,
|
|
716
|
-
codeAction: {
|
|
717
|
-
disableRuleComment: config.get<CodeActionSettings['disableRuleComment']>('codeAction.disableRuleComment', { enable: true, location: 'separateLine' as const, commentStyle: 'line' as const }),
|
|
718
|
-
showDocumentation: config.get<CodeActionSettings['showDocumentation']>('codeAction.showDocumentation', { enable: true })
|
|
719
|
-
}
|
|
720
|
-
};
|
|
721
|
-
const document: TextDocument | undefined = syncedDocuments.get(item.scopeUri);
|
|
722
|
-
if (document === undefined) {
|
|
723
|
-
result.push(settings);
|
|
724
|
-
continue;
|
|
725
|
-
}
|
|
726
|
-
if (config.get<boolean>('enabled', true)) {
|
|
727
|
-
settings.validate = validator.check(document);
|
|
728
|
-
}
|
|
729
|
-
if (settings.validate !== Validate.off) {
|
|
730
|
-
settings.format = !!config.get<boolean>('format.enable', false);
|
|
731
|
-
settings.codeActionOnSave.mode = CodeActionsOnSaveMode.from(config.get<CodeActionsOnSaveMode>('codeActionsOnSave.mode', CodeActionsOnSaveMode.all));
|
|
732
|
-
settings.codeActionOnSave.rules = CodeActionsOnSaveRules.from(config.get<string[] | null>('codeActionsOnSave.rules', null));
|
|
733
|
-
settings.codeActionOnSave.options = CodeActionsOnSaveOptions.from(config.get<ESLintOptions | null>('codeActionsOnSave.options', null));
|
|
734
|
-
}
|
|
735
|
-
if (workspaceFolder !== undefined) {
|
|
736
|
-
settings.workspaceFolder = {
|
|
737
|
-
name: workspaceFolder.name,
|
|
738
|
-
uri: client.code2ProtocolConverter.asUri(workspaceFolder.uri)
|
|
739
|
-
};
|
|
740
|
-
}
|
|
741
|
-
const workingDirectories = config.get<(string | LegacyDirectoryItem | DirectoryItem | PatternItem | ModeItem)[] | undefined>('workingDirectories', undefined);
|
|
742
|
-
if (Array.isArray(workingDirectories)) {
|
|
743
|
-
let workingDirectory: ModeItem | DirectoryItem | undefined = undefined;
|
|
744
|
-
const workspaceFolderPath = workspaceFolder && workspaceFolder.uri.scheme === 'file' ? workspaceFolder.uri.fsPath : undefined;
|
|
745
|
-
for (const entry of workingDirectories) {
|
|
746
|
-
let directory: string | undefined;
|
|
747
|
-
let pattern: string | undefined;
|
|
748
|
-
let noCWD = false;
|
|
749
|
-
if (Is.string(entry)) {
|
|
750
|
-
directory = entry;
|
|
751
|
-
} else if (LegacyDirectoryItem.is(entry)) {
|
|
752
|
-
directory = entry.directory;
|
|
753
|
-
noCWD = !entry.changeProcessCWD;
|
|
754
|
-
} else if (DirectoryItem.is(entry)) {
|
|
755
|
-
directory = entry.directory;
|
|
756
|
-
if (entry['!cwd'] !== undefined) {
|
|
757
|
-
noCWD = entry['!cwd'];
|
|
758
|
-
}
|
|
759
|
-
} else if (PatternItem.is(entry)) {
|
|
760
|
-
pattern = entry.pattern;
|
|
761
|
-
if (entry['!cwd'] !== undefined) {
|
|
762
|
-
noCWD = entry['!cwd'];
|
|
763
|
-
}
|
|
764
|
-
} else if (ModeItem.is(entry)) {
|
|
765
|
-
workingDirectory = entry;
|
|
766
|
-
continue;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
let itemValue: string | undefined;
|
|
770
|
-
if (directory !== undefined || pattern !== undefined) {
|
|
771
|
-
const filePath = document.uri.scheme === 'file' ? document.uri.fsPath : undefined;
|
|
772
|
-
if (filePath !== undefined) {
|
|
773
|
-
if (directory !== undefined) {
|
|
774
|
-
directory = toOSPath(directory);
|
|
775
|
-
if (!path.isAbsolute(directory) && workspaceFolderPath !== undefined) {
|
|
776
|
-
directory = path.join(workspaceFolderPath, directory);
|
|
777
|
-
}
|
|
778
|
-
if (directory.charAt(directory.length - 1) !== path.sep) {
|
|
779
|
-
directory = directory + path.sep;
|
|
780
|
-
}
|
|
781
|
-
if (filePath.startsWith(directory)) {
|
|
782
|
-
itemValue = directory;
|
|
783
|
-
}
|
|
784
|
-
} else if (pattern !== undefined && pattern.length > 0) {
|
|
785
|
-
if (!path.posix.isAbsolute(pattern) && workspaceFolderPath !== undefined) {
|
|
786
|
-
pattern = path.posix.join(toPosixPath(workspaceFolderPath), pattern);
|
|
787
|
-
}
|
|
788
|
-
if (pattern.charAt(pattern.length - 1) !== path.posix.sep) {
|
|
789
|
-
pattern = pattern + path.posix.sep;
|
|
790
|
-
}
|
|
791
|
-
const regExp: RegExp | undefined = convert2RegExp(pattern);
|
|
792
|
-
if (regExp !== undefined) {
|
|
793
|
-
const match = regExp.exec(filePath);
|
|
794
|
-
if (match !== null && match.length > 0) {
|
|
795
|
-
itemValue = match[0];
|
|
796
|
-
}
|
|
797
|
-
}
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
if (itemValue !== undefined) {
|
|
802
|
-
if (workingDirectory === undefined || ModeItem.is(workingDirectory)) {
|
|
803
|
-
workingDirectory = { directory: itemValue, '!cwd': noCWD };
|
|
804
|
-
} else {
|
|
805
|
-
if (workingDirectory.directory.length < itemValue.length) {
|
|
806
|
-
workingDirectory.directory = itemValue;
|
|
807
|
-
workingDirectory['!cwd'] = noCWD;
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
}
|
|
812
|
-
settings.workingDirectory = workingDirectory;
|
|
813
|
-
}
|
|
814
|
-
result.push(settings);
|
|
815
|
-
}
|
|
816
|
-
return result;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
function parseRulesCustomizations(rawConfig: unknown): RuleCustomization[] {
|
|
820
|
-
if (!rawConfig || !Array.isArray(rawConfig)) {
|
|
821
|
-
return [];
|
|
822
|
-
}
|
|
823
|
-
|
|
824
|
-
return rawConfig.map(rawValue => {
|
|
825
|
-
if (typeof rawValue.severity === 'string' && typeof rawValue.rule === 'string') {
|
|
826
|
-
if (typeof rawValue.fixable === 'boolean') {
|
|
827
|
-
return {
|
|
828
|
-
severity: rawValue.severity,
|
|
829
|
-
rule: rawValue.rule,
|
|
830
|
-
fixable: rawValue.fixable
|
|
831
|
-
};
|
|
832
|
-
} else {
|
|
833
|
-
return {
|
|
834
|
-
severity: rawValue.severity,
|
|
835
|
-
rule: rawValue.rule,
|
|
836
|
-
};
|
|
837
|
-
}
|
|
838
|
-
}
|
|
839
|
-
|
|
840
|
-
return undefined;
|
|
841
|
-
}).filter((value): value is RuleCustomization => !!value);
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
function getRuleCustomizations(config: WorkspaceConfiguration, uri: Uri): RuleCustomization[] {
|
|
845
|
-
let customizations: RuleCustomization[] | undefined = undefined;
|
|
846
|
-
if (uri.scheme === 'vscode-notebook-cell') {
|
|
847
|
-
customizations = config.get<RuleCustomization[] | undefined>('notebooks.rules.customizations', undefined);
|
|
848
|
-
}
|
|
849
|
-
if (customizations === undefined || customizations === null) {
|
|
850
|
-
customizations = config.get<RuleCustomization[] | undefined>('rules.customizations');
|
|
851
|
-
}
|
|
852
|
-
return parseRulesCustomizations(customizations);
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
function getTextDocument(uri: Uri): TextDocument | undefined {
|
|
856
|
-
return syncedDocuments.get(uri.toString());
|
|
857
|
-
}
|
|
858
|
-
|
|
859
|
-
function updateDocumentStatus(params: StatusParams): void {
|
|
860
|
-
const needsSelectorUpdate = !documentStatus.has(params.uri);
|
|
861
|
-
documentStatus.set(params.uri, { state: params.state });
|
|
862
|
-
if (needsSelectorUpdate) {
|
|
863
|
-
updateLanguageStatusSelector();
|
|
864
|
-
}
|
|
865
|
-
const textDocument = syncedDocuments.get(params.uri);
|
|
866
|
-
if (textDocument !== undefined) {
|
|
867
|
-
let performanceInfo = performanceStatus.get(textDocument.languageId);
|
|
868
|
-
if (performanceInfo === undefined) {
|
|
869
|
-
performanceInfo = PerformanceStatus.defaultValue;
|
|
870
|
-
performanceStatus.set(textDocument.languageId, performanceInfo);
|
|
871
|
-
} else {
|
|
872
|
-
performanceInfo.firstReport = false;
|
|
873
|
-
}
|
|
874
|
-
performanceInfo.validationTime = params.validationTime ?? 0;
|
|
875
|
-
}
|
|
876
|
-
updateStatusBar(textDocument);
|
|
877
|
-
}
|
|
878
|
-
|
|
879
|
-
function updateLanguageStatusSelector(): void {
|
|
880
|
-
const selector: VDocumentFilter[] = [];
|
|
881
|
-
for (const key of documentStatus.keys()) {
|
|
882
|
-
const uri: Uri = Uri.parse(key);
|
|
883
|
-
const document = syncedDocuments.get(key);
|
|
884
|
-
const filter: VDocumentFilter = {
|
|
885
|
-
scheme: uri.scheme,
|
|
886
|
-
pattern: uri.fsPath,
|
|
887
|
-
language: document?.languageId
|
|
888
|
-
};
|
|
889
|
-
selector.push(filter);
|
|
890
|
-
}
|
|
891
|
-
languageStatus.selector = selector;
|
|
892
|
-
}
|
|
893
|
-
|
|
894
|
-
function acknowledgePerformanceStatus(): void {
|
|
895
|
-
const activeTextDocument = Window.activeTextEditor?.document;
|
|
896
|
-
if (activeTextDocument === undefined) {
|
|
897
|
-
return;
|
|
898
|
-
}
|
|
899
|
-
const performanceInfo = performanceStatus.get(activeTextDocument.languageId);
|
|
900
|
-
if (performanceInfo === undefined || performanceInfo.reported === 0) {
|
|
901
|
-
return;
|
|
902
|
-
}
|
|
903
|
-
performanceInfo.acknowledged = true;
|
|
904
|
-
updateStatusBar(activeTextDocument);
|
|
905
|
-
}
|
|
906
|
-
|
|
907
|
-
function updateStatusBar(textDocument: TextDocument | undefined) {
|
|
908
|
-
const activeTextDocument = textDocument ?? Window.activeTextEditor?.document;
|
|
909
|
-
if (activeTextDocument === undefined || serverRunning === false) {
|
|
910
|
-
return;
|
|
911
|
-
}
|
|
912
|
-
const performanceInfo = performanceStatus.get(activeTextDocument.languageId);
|
|
913
|
-
const statusInfo = documentStatus.get(activeTextDocument.uri.toString()) ?? { state: Status.ok};
|
|
914
|
-
|
|
915
|
-
let validationBudget = Workspace.getConfiguration('eslint', activeTextDocument).get<TimeBudget>('timeBudget.onValidation', { warn: 4000, error: 8000 });
|
|
916
|
-
if (validationBudget.warn < 0 || validationBudget.error < 0) {
|
|
917
|
-
validationBudget = {
|
|
918
|
-
warn: validationBudget.warn < 0 ? Number.MAX_VALUE : validationBudget.warn,
|
|
919
|
-
error: validationBudget.error < 0 ? Number.MAX_VALUE : validationBudget.error
|
|
920
|
-
};
|
|
921
|
-
}
|
|
922
|
-
let fixesBudget = Workspace.getConfiguration('eslint', activeTextDocument).get<TimeBudget>('timeBudget.onFixes', { warn: 3000, error: 6000 });
|
|
923
|
-
if (fixesBudget.warn < 0 || fixesBudget.error < 0) {
|
|
924
|
-
fixesBudget = {
|
|
925
|
-
warn: fixesBudget.warn < 0 ? Number.MAX_VALUE : fixesBudget.warn,
|
|
926
|
-
error: fixesBudget.error < 0 ? Number.MAX_VALUE : fixesBudget.error
|
|
927
|
-
};
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
let severity: LanguageStatusSeverity = LanguageStatusSeverity.Information;
|
|
931
|
-
const [timeTaken, detail, message, timeBudget] = function(): [number, string | undefined, string, TimeBudget] {
|
|
932
|
-
if (performanceInfo === undefined || performanceInfo.firstReport || performanceInfo.acknowledged) {
|
|
933
|
-
return [-1, undefined, '', { warn: 0, error: 0 }];
|
|
934
|
-
}
|
|
935
|
-
if ((performanceInfo.fixTime) > (performanceInfo.validationTime)) {
|
|
936
|
-
const timeTaken = Math.max(performanceInfo.fixTime, performanceInfo.reported);
|
|
937
|
-
return [
|
|
938
|
-
timeTaken,
|
|
939
|
-
timeTaken > fixesBudget.warn ? `Computing fixes took ${timeTaken}ms` : undefined,
|
|
940
|
-
`Computing fixes during save for file ${activeTextDocument.uri.toString()} during save took ${timeTaken}ms. Please check the ESLint rules for performance issues.`,
|
|
941
|
-
fixesBudget
|
|
942
|
-
];
|
|
943
|
-
} else if ((performanceInfo.validationTime) > 0) {
|
|
944
|
-
const timeTaken = Math.max(performanceInfo.validationTime, performanceInfo.reported);
|
|
945
|
-
return [
|
|
946
|
-
timeTaken,
|
|
947
|
-
timeTaken > validationBudget.warn ? `Validation took ${timeTaken}ms` : undefined,
|
|
948
|
-
`Linting file ${activeTextDocument.uri.toString()} took ${timeTaken}ms. Please check the ESLint rules for performance issues.`,
|
|
949
|
-
validationBudget
|
|
950
|
-
];
|
|
951
|
-
}
|
|
952
|
-
return [-1, undefined, '', { warn: 0, error: 0 }];
|
|
953
|
-
}();
|
|
954
|
-
|
|
955
|
-
switch (statusInfo.state) {
|
|
956
|
-
case Status.ok:
|
|
957
|
-
break;
|
|
958
|
-
case Status.warn:
|
|
959
|
-
severity = LanguageStatusSeverity.Warning;
|
|
960
|
-
break;
|
|
961
|
-
case Status.error:
|
|
962
|
-
severity = LanguageStatusSeverity.Error;
|
|
963
|
-
break;
|
|
964
|
-
}
|
|
965
|
-
if (severity === LanguageStatusSeverity.Information && timeTaken > timeBudget.warn) {
|
|
966
|
-
severity = LanguageStatusSeverity.Warning;
|
|
967
|
-
}
|
|
968
|
-
if (severity === LanguageStatusSeverity.Warning && timeTaken > timeBudget.error) {
|
|
969
|
-
severity = LanguageStatusSeverity.Error;
|
|
970
|
-
}
|
|
971
|
-
if (timeTaken > timeBudget.warn && performanceInfo !== undefined) {
|
|
972
|
-
if (timeTaken > performanceInfo.reported) {
|
|
973
|
-
if (timeTaken > timeBudget.error) {
|
|
974
|
-
client.error(message);
|
|
975
|
-
} else {
|
|
976
|
-
client.warn(message);
|
|
977
|
-
}
|
|
978
|
-
}
|
|
979
|
-
}
|
|
980
|
-
|
|
981
|
-
if (detail !== undefined && languageStatus.detail !== detail) {
|
|
982
|
-
languageStatus.detail = detail;
|
|
983
|
-
}
|
|
984
|
-
if (languageStatus.severity !== severity) {
|
|
985
|
-
languageStatus.severity = severity;
|
|
986
|
-
}
|
|
987
|
-
if (performanceInfo !== undefined) {
|
|
988
|
-
performanceInfo.reported = Math.max(performanceInfo.reported, timeTaken);
|
|
989
|
-
}
|
|
990
|
-
}
|
|
991
|
-
}
|
|
992
|
-
}
|