Mark add missing imports as preferred fixes
Allow auto fixing add missing imports if: - There is only one possible import - And there are no better fixes (such as spelling changes)
This commit is contained in:
parent
541b9eb7a6
commit
39fb3b1065
8 changed files with 92 additions and 21 deletions
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
|
@ -310,7 +310,7 @@
|
||||||
"name": "TypeScript Extension Tests",
|
"name": "TypeScript Extension Tests",
|
||||||
"runtimeExecutable": "${execPath}",
|
"runtimeExecutable": "${execPath}",
|
||||||
"args": [
|
"args": [
|
||||||
"${workspaceFolder}/extensions/typescript-language-features/test-fixtures",
|
"${workspaceFolder}/extensions/typescript-language-features/test-workspace",
|
||||||
"--extensionDevelopmentPath=${workspaceFolder}/extensions/typescript-language-features",
|
"--extensionDevelopmentPath=${workspaceFolder}/extensions/typescript-language-features",
|
||||||
"--extensionTestsPath=${workspaceFolder}/extensions/typescript-language-features/out/test"
|
"--extensionTestsPath=${workspaceFolder}/extensions/typescript-language-features/out/test"
|
||||||
],
|
],
|
||||||
|
|
|
@ -59,6 +59,7 @@ const indentationFilter = [
|
||||||
// except specific folders
|
// except specific folders
|
||||||
'!test/automation/out/**',
|
'!test/automation/out/**',
|
||||||
'!test/smoke/out/**',
|
'!test/smoke/out/**',
|
||||||
|
'!extensions/typescript-language-features/test-workspace/**',
|
||||||
'!extensions/vscode-api-tests/testWorkspace/**',
|
'!extensions/vscode-api-tests/testWorkspace/**',
|
||||||
'!extensions/vscode-api-tests/testWorkspace2/**',
|
'!extensions/vscode-api-tests/testWorkspace2/**',
|
||||||
'!build/monaco/**',
|
'!build/monaco/**',
|
||||||
|
|
|
@ -333,17 +333,18 @@ const fixAllErrorCodes = new Map<number, number>([
|
||||||
[2345, 2339],
|
[2345, 2339],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const preferredFixes = new Map<string, /* priorty */number>([
|
const preferredFixes = new Map<string, { readonly value: number, readonly thereCanOnlyBeOne?: boolean }>([
|
||||||
[fixNames.annotateWithTypeFromJSDoc, 0],
|
[fixNames.annotateWithTypeFromJSDoc, { value: 1 }],
|
||||||
[fixNames.constructorForDerivedNeedSuperCall, 0],
|
[fixNames.constructorForDerivedNeedSuperCall, { value: 1 }],
|
||||||
[fixNames.extendsInterfaceBecomesImplements, 0],
|
[fixNames.extendsInterfaceBecomesImplements, { value: 1 }],
|
||||||
[fixNames.awaitInSyncFunction, 0],
|
[fixNames.awaitInSyncFunction, { value: 1 }],
|
||||||
[fixNames.classIncorrectlyImplementsInterface, 1],
|
[fixNames.classIncorrectlyImplementsInterface, { value: 1 }],
|
||||||
[fixNames.unreachableCode, 0],
|
[fixNames.unreachableCode, { value: 1 }],
|
||||||
[fixNames.unusedIdentifier, 0],
|
[fixNames.unusedIdentifier, { value: 1 }],
|
||||||
[fixNames.forgottenThisPropertyAccess, 0],
|
[fixNames.forgottenThisPropertyAccess, { value: 1 }],
|
||||||
[fixNames.spelling, 1],
|
[fixNames.spelling, { value: 2 }],
|
||||||
[fixNames.addMissingAwait, 0],
|
[fixNames.addMissingAwait, { value: 1 }],
|
||||||
|
[fixNames.fixImport, { value: 0, thereCanOnlyBeOne: true }],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
function isPreferredFix(
|
function isPreferredFix(
|
||||||
|
@ -354,20 +355,30 @@ function isPreferredFix(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const priority = preferredFixes.get(action.tsAction.fixName);
|
const fixPriority = preferredFixes.get(action.tsAction.fixName);
|
||||||
if (typeof priority === 'undefined') {
|
if (!fixPriority) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return allActions.every(otherAction => {
|
return allActions.every(otherAction => {
|
||||||
if (otherAction.tsAction === action.tsAction) {
|
if (otherAction === action) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const otherPriority = preferredFixes.get(otherAction.tsAction.fixName);
|
|
||||||
if (typeof otherPriority === 'undefined') {
|
if (otherAction.isFixAll) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return priority >= otherPriority;
|
|
||||||
|
const otherFixPriority = preferredFixes.get(otherAction.tsAction.fixName);
|
||||||
|
if (!otherFixPriority || otherFixPriority.value < fixPriority.value) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fixPriority.thereCanOnlyBeOne && action.tsAction.fixName === otherAction.tsAction.fixName) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,11 @@
|
||||||
|
|
||||||
import * as assert from 'assert';
|
import * as assert from 'assert';
|
||||||
import 'mocha';
|
import 'mocha';
|
||||||
|
import { join } from 'path';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import { disposeAll } from '../utils/dispose';
|
import { disposeAll } from '../utils/dispose';
|
||||||
import { createTestEditor, joinLines, wait } from './testUtils';
|
import { createTestEditor, joinLines, wait } from './testUtils';
|
||||||
|
|
||||||
const testDocumentUri = vscode.Uri.parse('untitled:test.ts');
|
|
||||||
|
|
||||||
|
|
||||||
suite('TypeScript Quick Fix', () => {
|
suite('TypeScript Quick Fix', () => {
|
||||||
|
|
||||||
const _disposables: vscode.Disposable[] = [];
|
const _disposables: vscode.Disposable[] = [];
|
||||||
|
@ -23,6 +21,8 @@ suite('TypeScript Quick Fix', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Fix all should not be marked as preferred #97866', async () => {
|
test('Fix all should not be marked as preferred #97866', async () => {
|
||||||
|
const testDocumentUri = vscode.Uri.parse('untitled:test.ts');
|
||||||
|
|
||||||
const editor = await createTestEditor(testDocumentUri,
|
const editor = await createTestEditor(testDocumentUri,
|
||||||
`export const _ = 1;`,
|
`export const _ = 1;`,
|
||||||
`const a$0 = 1;`,
|
`const a$0 = 1;`,
|
||||||
|
@ -40,4 +40,57 @@ suite('TypeScript Quick Fix', () => {
|
||||||
`const b = 2;`,
|
`const b = 2;`,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Add import should be a preferred fix if there is only one possible import', async () => {
|
||||||
|
await createTestEditor(workspaceFile('foo.ts'),
|
||||||
|
`export const foo = 1;`);
|
||||||
|
|
||||||
|
const editor = await createTestEditor(workspaceFile('index.ts'),
|
||||||
|
`export const _ = 1;`,
|
||||||
|
`foo$0;`
|
||||||
|
);
|
||||||
|
|
||||||
|
await wait(3000);
|
||||||
|
|
||||||
|
await vscode.commands.executeCommand('editor.action.autoFix');
|
||||||
|
|
||||||
|
await wait(500);
|
||||||
|
|
||||||
|
assert.strictEqual(editor.document.getText(), joinLines(
|
||||||
|
`import { foo } from "./foo";`,
|
||||||
|
``,
|
||||||
|
`export const _ = 1;`,
|
||||||
|
`foo;`
|
||||||
|
));
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Add import should not be a preferred fix if are multiple possible imports', async () => {
|
||||||
|
await createTestEditor(workspaceFile('foo.ts'),
|
||||||
|
`export const foo = 1;`);
|
||||||
|
|
||||||
|
await createTestEditor(workspaceFile('bar.ts'),
|
||||||
|
`export const foo = 1;`);
|
||||||
|
|
||||||
|
const editor = await createTestEditor(workspaceFile('index.ts'),
|
||||||
|
`export const _ = 1;`,
|
||||||
|
`foo$0;`
|
||||||
|
);
|
||||||
|
|
||||||
|
await wait(3000);
|
||||||
|
|
||||||
|
await vscode.commands.executeCommand('editor.action.autoFix');
|
||||||
|
|
||||||
|
await wait(500);
|
||||||
|
|
||||||
|
assert.strictEqual(editor.document.getText(), joinLines(
|
||||||
|
`export const _ = 1;`,
|
||||||
|
`foo;`
|
||||||
|
));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function workspaceFile(fileName: string) {
|
||||||
|
return vscode.Uri.file(join(vscode.workspace.rootPath!, fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
// export const foo = 1;
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2018"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue