Skip to content

Commit 0591e1b

Browse files
committed
Simplify Testing
1 parent c650c33 commit 0591e1b

7 files changed

+68
-94
lines changed

src/harness/fourslash.ts

Lines changed: 34 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -92,18 +92,6 @@ namespace FourSlash {
9292
end: number;
9393
}
9494

95-
export interface CodeFixIdentifier {
96-
/**
97-
* Error code to search over for codefix.
98-
*/
99-
code: number;
100-
/**
101-
* In a file where there is more than one error with code `code`, `count` refers
102-
* to which 0-indexed codefix, sorted by order of occurence, to consider.
103-
*/
104-
count: number;
105-
}
106-
10795
export import IndentStyle = ts.IndentStyle;
10896

10997
const entityMap = ts.createMap({
@@ -1609,12 +1597,6 @@ namespace FourSlash {
16091597
return runningOffset;
16101598
}
16111599

1612-
private applyCodeAction(action: ts.CodeAction): void {
1613-
for (const filechange of action.changes) {
1614-
this.applyEdits(filechange.fileName, filechange.textChanges, /*isFormattingEdit*/ false);
1615-
}
1616-
}
1617-
16181600
public copyFormatOptions(): ts.FormatCodeSettings {
16191601
return ts.clone(this.formatCodeSettings);
16201602
}
@@ -2034,31 +2016,22 @@ namespace FourSlash {
20342016

20352017
/**
20362018
* Compares expected text to the text that would be in the sole range
2037-
* (ie: [|...|]) in the file after applying the codefix corresponding
2038-
* to the error with errorCode, or of the sole error in the source file.
2019+
* (ie: [|...|]) in the file after applying the codefix sole codefix
2020+
* in the source file.
20392021
*
20402022
* Because codefixes are only applied on the working file, it is unsafe
20412023
* to apply this more than once (consider a refactoring across files).
20422024
*/
2043-
public verifyRangeAfterCodeFix(expectedText: string, codeFixIdentifier?: CodeFixIdentifier) {
2025+
public verifyRangeAfterCodeFix(expectedText: string) {
20442026
const ranges = this.getRanges();
20452027
if (ranges.length !== 1) {
20462028
this.raiseError("Exactly one range should be specified in the testfile.");
20472029
}
20482030

20492031
const fileName = this.activeFile.fileName;
2050-
const codeFix: ts.CodeAction = this.getCodeFix(fileName, codeFixIdentifier);
20512032

2052-
if (!codeFix) {
2053-
this.raiseError("Should find exactly one codefix, but none found.");
2054-
}
2055-
2056-
const fileChange = ts.find(codeFix.changes, change => change.fileName === fileName);
2057-
if (!fileChange) {
2058-
this.raiseError("CodeFix found doesn't provide any changes in this file.");
2059-
}
2033+
this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName));
20602034

2061-
this.applyEdits(fileChange.fileName, fileChange.textChanges, /*isFormattingEdit*/ false);
20622035
const actualText = this.rangeText(ranges[0]);
20632036

20642037
if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) {
@@ -2069,33 +2042,16 @@ namespace FourSlash {
20692042
/**
20702043
* Applies fixes for the errors in fileName and compares the results to
20712044
* expectedContents after all fixes have been applied.
2072-
*
2073-
* It is safe to apply this multiple times in a single test.
2074-
*
2045+
20752046
* Note: applying one codefix may generate another (eg: remove duplicate implements
20762047
* may generate an extends -> interface conversion fix).
20772048
* @param expectedContents The contents of the file after the fixes are applied.
20782049
* @param fileName The file to check. If not supplied, the current open file is used.
2079-
* @param errorsToFix An array of errors for which quickfixes will be applied. If not
2080-
* supplied, all codefixes in the file are applied until none are left, starting from
2081-
* the first available codefix.
2082-
*
20832050
*/
2084-
public verifyFileAfterCodeFix(expectedContents: string, fileName?: string, codeFixIdentifier?: CodeFixIdentifier) {
2051+
public verifyFileAfterCodeFix(expectedContents: string, fileName?: string) {
20852052
fileName = fileName ? fileName : this.activeFile.fileName;
20862053

2087-
const codeFix = this.getCodeFix(fileName, codeFixIdentifier);
2088-
2089-
if (codeFix === undefined) {
2090-
if (codeFixIdentifier) {
2091-
this.raiseError(`Couldn't find the ${codeFixIdentifier.count}'th error with code ${codeFixIdentifier.code}.`);
2092-
}
2093-
else {
2094-
this.raiseError("No code fix could be found.");
2095-
}
2096-
}
2097-
2098-
this.applyCodeAction(codeFix);
2054+
this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName));
20992055

21002056
const actualContents: string = this.getFileContent(fileName);
21012057
if (this.removeWhitespace(actualContents) !== this.removeWhitespace(expectedContents)) {
@@ -2106,30 +2062,31 @@ namespace FourSlash {
21062062
/**
21072063
* Rerieves a codefix satisfying the parameters, or undefined if no such codefix is found.
21082064
* @param fileName Path to file where error should be retrieved from.
2109-
* @param error We get the `error.count`'th codefix with code `error.code`.
2110-
*
2111-
* If undefined, we get the first codefix available.
21122065
*/
2113-
private getCodeFix(fileName: string, error?: CodeFixIdentifier): ts.CodeAction | undefined {
2066+
private getCodeFixActions(fileName: string): ts.CodeAction[] {
21142067
const diagnostics: ts.Diagnostic[] = this.getDiagnostics(fileName);
2115-
const errorCount = error ? error.count : 0;
21162068

2117-
let countSeen = 0;
2069+
let actions: ts.CodeAction[] = undefined;
21182070
for (const diagnostic of diagnostics) {
2119-
if (error && error.code !== diagnostic.code) {
2120-
continue;
2121-
}
2122-
const action = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
2123-
if (action) {
2124-
if (action.length > errorCount - countSeen) {
2125-
return action[errorCount - countSeen];
2126-
}
2127-
else {
2128-
countSeen += action.length;
2129-
}
2071+
const newActions = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]);
2072+
if (newActions && newActions.length) {
2073+
actions = actions ? actions.concat(newActions) : newActions;
21302074
}
21312075
}
2132-
return undefined;
2076+
return actions;
2077+
}
2078+
2079+
private applyCodeFixActions(fileName: string, actions: ts.CodeAction[]): void {
2080+
if (!(actions && actions.length === 1)) {
2081+
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`);
2082+
}
2083+
2084+
const fileChanges = ts.find(actions[0].changes, change => change.fileName === fileName);
2085+
if (!fileChanges) {
2086+
this.raiseError("The CodeFix found doesn't provide any changes in this file.");
2087+
}
2088+
2089+
this.applyEdits(fileChanges.fileName, fileChanges.textChanges, /*isFormattingEdit*/ false);
21332090
}
21342091

21352092
public verifyDocCommentTemplate(expected?: ts.TextInsertion) {
@@ -2404,8 +2361,8 @@ namespace FourSlash {
24042361
}
24052362
}
24062363

2407-
public verifyCodeFixAvailable(negative: boolean, errorCode?: number) {
2408-
const codeFix = this.getCodeFix(this.activeFile.fileName, errorCode ? { code: errorCode, count: 0 } : undefined);
2364+
public verifyCodeFixAvailable(negative: boolean) {
2365+
const codeFix = this.getCodeFixActions(this.activeFile.fileName);
24092366

24102367
if (negative && codeFix) {
24112368
this.raiseError(`verifyCodeFixAvailable failed - expected no fixes but found one.`);
@@ -3199,8 +3156,8 @@ namespace FourSlashInterface {
31993156
this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace);
32003157
}
32013158

3202-
public codeFixAvailable(errorCode?: number) {
3203-
this.state.verifyCodeFixAvailable(this.negative, errorCode);
3159+
public codeFixAvailable() {
3160+
this.state.verifyCodeFixAvailable(this.negative);
32043161
}
32053162
}
32063163

@@ -3385,12 +3342,12 @@ namespace FourSlashInterface {
33853342
this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true);
33863343
}
33873344

3388-
public rangeAfterCodeFix(expectedText: string, codeFixidentifier?: FourSlash.CodeFixIdentifier): void {
3389-
this.state.verifyRangeAfterCodeFix(expectedText, codeFixidentifier);
3345+
public rangeAfterCodeFix(expectedText: string): void {
3346+
this.state.verifyRangeAfterCodeFix(expectedText);
33903347
}
33913348

3392-
public fileAfterCodeFix(expectedContents: string, fileName?: string, codeFixidentifier?: FourSlash.CodeFixIdentifier): void {
3393-
this.state.verifyFileAfterCodeFix(expectedContents, fileName, codeFixidentifier);
3349+
public fileAfterCodeFix(expectedContents: string, fileName?: string): void {
3350+
this.state.verifyFileAfterCodeFix(expectedContents, fileName);
33943351
}
33953352

33963353
public navigationBar(json: any) {

tests/cases/fourslash/codeFixClassExtendsAbstractSomePropertiesPresent.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//// }
88
////
99
//// class C extends A {[| |]
10-
//// constructor(public x: number) { }
10+
//// constructor(public x: number) { super(); }
1111
//// y: number;
1212
//// }
1313

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// interface I1 {
4+
//// x: number;
5+
//// }
6+
//// interface I2 {
7+
//// x: number;
8+
//// }
9+
////
10+
//// class C implements I1,I2 {[|
11+
//// |]}
12+
13+
verify.codeFixAvailable();

tests/cases/fourslash/codeFixUnImplementedInterfaceDuplicateMember.ts renamed to tests/cases/fourslash/codeFixUnImplementedInterfaceDuplicateMember2.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
//// x: number;
88
//// }
99
////
10-
//// class C1 implements I1,I2 {[|
11-
//// |]}
10+
//// class C implements I1,I2 {
11+
//// x: number;
12+
//// }
1213

13-
verify.rangeAfterCodeFix(`
14-
x: number;
15-
`);
1614
verify.not.codeFixAvailable();

tests/cases/fourslash/codeFixUnimplementedInterfaceMissingMultipleImplementsIntersection.ts renamed to tests/cases/fourslash/codeFixUnimplementedInterfaceMissingMultipleImplementsIntersection1.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,4 @@
1010
//// class C implements I1,I2 {[|
1111
//// |]}
1212

13-
verify.rangeAfterCodeFix(`
14-
x: number;
15-
`);
16-
17-
verify.not.codeFixAvailable();
13+
verify.codeFixAvailable();
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
//// interface I1 {
4+
//// x: number;
5+
//// }
6+
//// interface I2 {
7+
//// x: string;
8+
//// }
9+
////
10+
//// class C implements I1,I2 {
11+
//// x: string;
12+
//// }
13+
14+
verify.not.codeFixAvailable();

tests/cases/fourslash/fourslash.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,6 @@ declare namespace FourSlashInterface {
9898
start: number;
9999
end: number;
100100
}
101-
interface CodeFixIdentifier {
102-
code: number;
103-
count: number
104-
}
105101
class test_ {
106102
markers(): Marker[];
107103
markerNames(): string[];
@@ -214,8 +210,8 @@ declare namespace FourSlashInterface {
214210
noMatchingBracePositionInCurrentFile(bracePosition: number): void;
215211
DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean): void;
216212
noDocCommentTemplate(): void;
217-
rangeAfterCodeFix(expectedText: string, CodeFixIdentifier?: CodeFixIdentifier): void;
218-
fileAfterCodeFix(expectedContents: string, fileName?: string, CodeFixIdentifier?: CodeFixIdentifier): void;
213+
rangeAfterCodeFix(expectedText: string): void;
214+
fileAfterCodeFix(expectedContents: string, fileName?: string): void;
219215

220216
navigationBar(json: any): void;
221217
navigationTree(json: any): void;

0 commit comments

Comments
 (0)