|
1 | | -// |
| 1 | +// |
2 | 2 | // Copyright (c) Microsoft Corporation. All rights reserved. |
3 | 3 | // |
4 | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
@@ -427,7 +427,7 @@ namespace FourSlash { |
427 | 427 |
|
428 | 428 | if (exists !== negative) { |
429 | 429 | this.printErrorLog(negative, this.getAllDiagnostics()); |
430 | | - throw new Error("Failure between markers: " + startMarkerName + ", " + endMarkerName); |
| 430 | + throw new Error(`Failure between markers: '${startMarkerName}', '${endMarkerName}'`); |
431 | 431 | } |
432 | 432 | } |
433 | 433 |
|
@@ -742,7 +742,6 @@ namespace FourSlash { |
742 | 742 | } |
743 | 743 | } |
744 | 744 |
|
745 | | - |
746 | 745 | public verifyCompletionListAllowsNewIdentifier(negative: boolean) { |
747 | 746 | const completions = this.getCompletionListAtCaret(); |
748 | 747 |
|
@@ -1611,7 +1610,7 @@ namespace FourSlash { |
1611 | 1610 | if (isFormattingEdit) { |
1612 | 1611 | const newContent = this.getFileContent(fileName); |
1613 | 1612 |
|
1614 | | - if (newContent.replace(/\s/g, "") !== oldContent.replace(/\s/g, "")) { |
| 1613 | + if (this.removeWhitespace(newContent) !== this.removeWhitespace(oldContent)) { |
1615 | 1614 | this.raiseError("Formatting operation destroyed non-whitespace content"); |
1616 | 1615 | } |
1617 | 1616 | } |
@@ -1677,6 +1676,10 @@ namespace FourSlash { |
1677 | 1676 | } |
1678 | 1677 | } |
1679 | 1678 |
|
| 1679 | + private removeWhitespace(text: string): string { |
| 1680 | + return text.replace(/\s/g, ""); |
| 1681 | + } |
| 1682 | + |
1680 | 1683 | public goToBOF() { |
1681 | 1684 | this.goToPosition(0); |
1682 | 1685 | } |
@@ -2038,6 +2041,47 @@ namespace FourSlash { |
2038 | 2041 | } |
2039 | 2042 | } |
2040 | 2043 |
|
| 2044 | + private getCodeFixes(errorCode?: number) { |
| 2045 | + const fileName = this.activeFile.fileName; |
| 2046 | + const diagnostics = this.getDiagnostics(fileName); |
| 2047 | + |
| 2048 | + if (diagnostics.length === 0) { |
| 2049 | + this.raiseError("Errors expected."); |
| 2050 | + } |
| 2051 | + |
| 2052 | + if (diagnostics.length > 1 && errorCode !== undefined) { |
| 2053 | + this.raiseError("When there's more than one error, you must specify the errror to fix."); |
| 2054 | + } |
| 2055 | + |
| 2056 | + const diagnostic = !errorCode ? diagnostics[0] : ts.find(diagnostics, d => d.code == errorCode); |
| 2057 | + |
| 2058 | + return this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [diagnostic.code]); |
| 2059 | + } |
| 2060 | + |
| 2061 | + public verifyCodeFixAtPosition(expectedText: string, errorCode?: number) { |
| 2062 | + const ranges = this.getRanges(); |
| 2063 | + if (ranges.length == 0) { |
| 2064 | + this.raiseError("At least one range should be specified in the testfile."); |
| 2065 | + } |
| 2066 | + |
| 2067 | + const actual = this.getCodeFixes(errorCode); |
| 2068 | + |
| 2069 | + if (!actual || actual.length == 0) { |
| 2070 | + this.raiseError("No codefixes returned."); |
| 2071 | + } |
| 2072 | + |
| 2073 | + if (actual.length > 1) { |
| 2074 | + this.raiseError("More than 1 codefix returned."); |
| 2075 | + } |
| 2076 | + |
| 2077 | + this.applyEdits(actual[0].changes[0].fileName, actual[0].changes[0].textChanges, /*isFormattingEdit*/ false); |
| 2078 | + const actualText = this.rangeText(ranges[0]); |
| 2079 | + |
| 2080 | + if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) { |
| 2081 | + this.raiseError(`Actual text doesn't match expected text. Actual: '${actualText}' Expected: '${expectedText}'`); |
| 2082 | + } |
| 2083 | + } |
| 2084 | + |
2041 | 2085 | public verifyDocCommentTemplate(expected?: ts.TextInsertion) { |
2042 | 2086 | const name = "verifyDocCommentTemplate"; |
2043 | 2087 | const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition); |
@@ -2309,6 +2353,18 @@ namespace FourSlash { |
2309 | 2353 | } |
2310 | 2354 | } |
2311 | 2355 |
|
| 2356 | + public verifyCodeFixAvailable(negative: boolean, errorCode?: number) { |
| 2357 | + const fixes = this.getCodeFixes(errorCode); |
| 2358 | + |
| 2359 | + if (negative && fixes && fixes.length > 0) { |
| 2360 | + this.raiseError(`verifyCodeFixAvailable failed - expected no fixes, actual: ${fixes.length}`); |
| 2361 | + } |
| 2362 | + |
| 2363 | + if (!negative && (fixes === undefined || fixes.length === 0)) { |
| 2364 | + this.raiseError(`verifyCodeFixAvailable failed - expected code fixes, actual: 0`); |
| 2365 | + } |
| 2366 | + } |
| 2367 | + |
2312 | 2368 | // Get the text of the entire line the caret is currently at |
2313 | 2369 | private getCurrentLineContent() { |
2314 | 2370 | const text = this.getFileContent(this.activeFile.fileName); |
@@ -3096,6 +3152,10 @@ namespace FourSlashInterface { |
3096 | 3152 | public isValidBraceCompletionAtPosition(openingBrace: string) { |
3097 | 3153 | this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace); |
3098 | 3154 | } |
| 3155 | + |
| 3156 | + public codeFixAvailable(errorCode?: number) { |
| 3157 | + this.state.verifyCodeFixAvailable(this.negative, errorCode); |
| 3158 | + } |
3099 | 3159 | } |
3100 | 3160 |
|
3101 | 3161 | export class Verify extends VerifyNegatable { |
@@ -3275,6 +3335,10 @@ namespace FourSlashInterface { |
3275 | 3335 | this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true); |
3276 | 3336 | } |
3277 | 3337 |
|
| 3338 | + public codeFixAtPosition(expectedText: string, errorCode?: number): void { |
| 3339 | + this.state.verifyCodeFixAtPosition(expectedText, errorCode); |
| 3340 | + } |
| 3341 | + |
3278 | 3342 | public navigationBar(json: any) { |
3279 | 3343 | this.state.verifyNavigationBar(json); |
3280 | 3344 | } |
|
0 commit comments