Improve verify.codeFixAvailable (#24325)

* Improve verify.codeFixAvailable

* Revert change to `verify.not.codeFixAvailable()`, and use `assertObjectsEqual` for better errors
This commit is contained in:
Andy 2018-05-22 16:04:39 -07:00 committed by GitHub
parent 56f33ad3bb
commit aed0eb6693
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 63 additions and 60 deletions

View File

@ -2998,30 +2998,11 @@ Actual: ${stringify(fullActual)}`);
}
}
public verifyCodeFixAvailable(negative: boolean, info: FourSlashInterface.VerifyCodeFixAvailableOptions[] | undefined) {
public verifyCodeFixAvailable(negative: boolean, expected: FourSlashInterface.VerifyCodeFixAvailableOptions[] | undefined): void {
assert(!negative || !expected);
const codeFixes = this.getCodeFixes(this.activeFile.fileName);
if (negative) {
if (codeFixes.length) {
this.raiseError(`verifyCodeFixAvailable failed - expected no fixes but found ${codeFixes.map(c => c.description)}.`);
}
return;
}
if (!codeFixes.length) {
this.raiseError(`verifyCodeFixAvailable failed - expected code fixes but none found.`);
}
codeFixes.forEach(fix => fix.changes.forEach(change => {
assert.isObject(change, `Invalid change in code fix: ${JSON.stringify(fix)}`);
change.textChanges.forEach(textChange => assert.isObject(textChange, `Invalid textChange in codeFix: ${JSON.stringify(fix)}`));
}));
if (info) {
assert.equal(info.length, codeFixes.length);
ts.zipWith(codeFixes, info, (fix, info) => {
assert.equal(fix.description, info.description);
this.assertObjectsEqual(fix.commands, info.commands);
});
}
const actuals = codeFixes.map((fix): FourSlashInterface.VerifyCodeFixAvailableOptions => ({ description: fix.description, commands: fix.commands }));
this.assertObjectsEqual(actuals, negative ? ts.emptyArray : expected);
}
public verifyApplicableRefactorAvailableAtMarker(negative: boolean, markerName: string) {

View File

@ -9,4 +9,7 @@
////
//// class C implements I1,I2 {[| |]}
verify.codeFixAvailable();
verify.codeFixAvailable([
{ description: "Implement interface 'I1'" },
{ description: "Implement interface 'I2'" },
]);

View File

@ -11,4 +11,4 @@
//// x: number;
//// }
verify.not.codeFixAvailable();
verify.not.codeFixAvailable();

View File

@ -9,4 +9,7 @@
////
//// class C implements I1,I2 {[| |]}
verify.codeFixAvailable();
verify.codeFixAvailable([
{ description: "Implement interface 'I1'" },
{ description: "Implement interface 'I2'" },
]);

View File

@ -11,4 +11,4 @@
//// x: string;
//// }
verify.not.codeFixAvailable();
verify.not.codeFixAvailable();

View File

@ -6,7 +6,7 @@
////
//// class B implements A {[| |]}
verify.not.codeFixAvailable();
verify.codeFixAvailable([]);
// TODO: (arozga) Get this working.
/*

View File

@ -4,10 +4,9 @@
//// x: T;
//// }
////
//// class C implements I<number> { }
verify.codeFixAvailable();
//// class C implements I<number> { }
// TODO: (arozga) Don't know how to instantiate in codeFix
// if instantiation is invalid.
// verify.not.codeFixAvailable();
// Should be verify.codeFixAvailable([]);
verify.codeFixAvailable([{ description: "Implement interface 'I<number>'" }]);

View File

@ -4,6 +4,6 @@
//// x: T;
//// }
////
//// class C implements I { }
//// class C implements I { }
verify.not.codeFixAvailable();
verify.not.codeFixAvailable();

View File

@ -4,7 +4,7 @@
//// x: T;
//// }
////
//// class C implements I { }
//// class C implements I { }
// T is not a declared symbol. There are a couple fixes:
// 1) Declare T.
@ -14,6 +14,6 @@
// In the latter two cases, it is premature to copy `x:T` into C.
// Since we can't guess the programmer's intent here, we do nothing.
verify.codeFixAvailable();
// TODO: (aozgaa) Acknowledge other errors on class/implemented interface/extended abstract class.
// verify.not.codeFixAvailable();
// Should be verify.codeFixAvailable([]);
verify.codeFixAvailable([{ description: "Implement interface 'I'" }]);

View File

@ -7,34 +7,54 @@
//// class TT { constructor () {} }
////
//// class AT extends A { a () {} }
////
////
//// class Foo {}
////
//// class T {
////
////
//// a: string;
////
////
//// static b: string;
////
////
//// private c: string;
////
////
//// d: number | undefined;
////
////
//// e: string | number;
////
////
//// f: 1;
////
////
//// g: "123" | "456";
////
////
//// h: boolean;
////
////
//// i: TT;
////
////
//// j: A;
////
////
//// k: AT;
////
////
//// l: Foo;
//// }
verify.codeFixAvailable()
function fixes(name: string, type: string, options: { isPrivate?: boolean, noInitializer?: boolean } = {}) {
return [
`Add 'undefined' type to property '${name}'`,
`Add definite assignment assertion to property '${options.isPrivate ? "private " : ""}${name}: ${type};'`,
...(options.noInitializer ? [] : [`Add initializer to property '${name}'`]),
].map(description => ({ description }));
}
verify.codeFixAvailable([
...fixes("a", "string"),
...fixes("c", "string", { isPrivate: true }),
...fixes("e", "string | number"),
...fixes("f", "1"),
...fixes("g", '"123" | "456"'),
...fixes("h", "boolean"),
...fixes("i", "TT"),
...fixes("j", "A", { noInitializer: true }),
...fixes("k", "AT"),
...fixes("l", "Foo"),
{ description: "Remove declaration for: 'c'" },
]);

View File

@ -9,4 +9,4 @@
//// }
////}
verify.not.codeFixAvailable();
verify.not.codeFixAvailable();

View File

@ -1,6 +1,6 @@
/// <reference path='fourslash.ts' />
// @jsx: react
// @jsx: react
// @jsxFactory: factory
// @Filename: /a.tsx
@ -10,5 +10,4 @@
//// }
////}
verify.not.codeFixAvailable();

View File

@ -13,4 +13,4 @@
////}
goTo.file("/b.ts");
verify.not.codeFixAvailable();
verify.not.codeFixAvailable();

View File

@ -14,4 +14,4 @@
//// let t: T<number>;
//// t.x;
verify.not.codeFixAvailable();
verify.not.codeFixAvailable();

View File

@ -6,5 +6,4 @@
////}
////f(
verify.not.codeFixAvailable([]);
verify.not.codeFixAvailable();

View File

@ -3,5 +3,4 @@
// @noImplicitAny: true
//// function ...q) {}} f(10);
verify.not.codeFixAvailable([]);
verify.not.codeFixAvailable();