async function computeAllFixes()

in server/src/eslintServer.ts [2279:2356]


async function computeAllFixes(identifier: VersionedTextDocumentIdentifier, mode: AllFixesMode): Promise<TextEdit[] | undefined> {
	const uri = identifier.uri;
	const textDocument = documents.get(uri)!;
	if (textDocument === undefined || identifier.version !== textDocument.version) {
		return undefined;
	}

	const settings = await resolveSettings(textDocument);

	if (settings.validate !== Validate.on || !TextDocumentSettings.hasLibrary(settings) || (mode === AllFixesMode.format && !settings.format)) {
		return [];
	}
	const filePath = getFilePath(textDocument);
	const problems = codeActions.get(uri);
	const originalContent = textDocument.getText();
	let start = Date.now();
	// Only use known fixes when running in onSave mode. See https://github.com/microsoft/vscode-eslint/issues/871
	// for details
	if (mode === AllFixesMode.onSave && settings.codeActionOnSave.mode === CodeActionsOnSaveMode.problems) {
		const result = problems !== undefined && problems.size > 0
			? new Fixes(problems).getApplicable().map(fix => FixableProblem.createTextEdit(textDocument, fix))
			: [];
		connection.tracer.log(`Computing all fixes took: ${Date.now() - start} ms.`);
		return result;
	} else {
		const saveConfig = filePath !== undefined && mode === AllFixesMode.onSave ? await getSaveRuleConfig(uri, settings) : undefined;
		const offRules = saveConfig?.offRules;
		const onRules = saveConfig?.onRules;
		let overrideConfig: Required<ConfigData> | undefined;
		if (offRules !== undefined) {
			overrideConfig = { rules: Object.create(null) };
			for (const ruleId of offRules) {
				overrideConfig.rules[ruleId] = 'off';
			}
		}
		return withESLintClass(async (eslintClass) => {
			const result: TextEdit[] = [];
			let fixes: TextEdit[] | undefined;
			if (problems !== undefined && problems.size > 0) {
				// We have override rules that turn rules off. Filter the fixes for these rules.
				if (offRules !== undefined) {
					const filtered: typeof problems = new Map();
					for (const [key, problem] of problems) {
						if (onRules?.has(problem.ruleId)) {
							filtered.set(key, problem);
						}
					}
					fixes = filtered.size > 0 ? new Fixes(filtered).getApplicable().map(fix => FixableProblem.createTextEdit(textDocument, fix)) : undefined;
				} else {
					fixes = new Fixes(problems).getApplicable().map(fix => FixableProblem.createTextEdit(textDocument, fix));
				}
			}
			const content = fixes !== undefined
				? TextDocument.applyEdits(textDocument, fixes)
				: originalContent;
			const reportResults = await eslintClass.lintText(content, { filePath });
			connection.tracer.log(`Computing all fixes took: ${Date.now() - start} ms.`);
			if (Array.isArray(reportResults) && reportResults.length === 1 && reportResults[0].output !== undefined) {
				const fixedContent = reportResults[0].output;
				start = Date.now();
				const diffs = stringDiff(originalContent, fixedContent, false);
				connection.tracer.log(`Computing minimal edits took: ${Date.now() - start} ms.`);
				for (const diff of diffs) {
					result.push({
						range: {
							start: textDocument.positionAt(diff.originalStart),
							end: textDocument.positionAt(diff.originalStart + diff.originalLength)
						},
						newText: fixedContent.substr(diff.modifiedStart, diff.modifiedLength)
					});
				}
			} else if (fixes !== undefined) {
				result.push(...fixes);
			}
			return result;
		}, settings, overrideConfig !== undefined ? { fix: true, overrideConfig } : { fix: true });
	}
}