mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-15 21:36:50 -05:00
Fourslash support
This commit is contained in:
@@ -115,6 +115,15 @@ namespace ts {
|
||||
return -1;
|
||||
}
|
||||
|
||||
export function firstOrUndefined<T>(array: T[], predicate: (x: T) => boolean): T {
|
||||
for (let i = 0, len = array.length; i < len; i++) {
|
||||
if (predicate(array[i])) {
|
||||
return array[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function indexOfAnyCharCode(text: string, charCodes: number[], start?: number): number {
|
||||
for (let i = start || 0, len = text.length; i < len; i++) {
|
||||
if (contains(charCodes, text.charCodeAt(i))) {
|
||||
|
||||
@@ -3031,5 +3031,33 @@
|
||||
"Unknown typing option '{0}'.": {
|
||||
"category": "Error",
|
||||
"code": 17010
|
||||
},
|
||||
"Add missing 'super()' call.": {
|
||||
"category": "CodeFix",
|
||||
"code": 90001
|
||||
},
|
||||
"Make 'super()' call the first statement in the constructor.": {
|
||||
"category": "CodeFix",
|
||||
"code": 90002
|
||||
},
|
||||
"Change 'extends' to 'implements'": {
|
||||
"category": "CodeFix",
|
||||
"code": 90003
|
||||
},
|
||||
"Remove unused identifiers": {
|
||||
"category": "CodeFix",
|
||||
"code": 90004
|
||||
},
|
||||
"Implement interface on reference": {
|
||||
"category": "CodeFix",
|
||||
"code": 90005
|
||||
},
|
||||
"Implement interface on class": {
|
||||
"category": "CodeFix",
|
||||
"code": 90006
|
||||
},
|
||||
"Implement inherited abstract class": {
|
||||
"category": "CodeFix",
|
||||
"code": 90007
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2547,6 +2547,7 @@ namespace ts {
|
||||
Warning,
|
||||
Error,
|
||||
Message,
|
||||
CodeFix,
|
||||
}
|
||||
|
||||
export enum ModuleResolutionKind {
|
||||
|
||||
@@ -384,7 +384,7 @@ namespace FourSlash {
|
||||
|
||||
if (exists !== negative) {
|
||||
this.printErrorLog(negative, this.getAllDiagnostics());
|
||||
throw new Error("Failure between markers: " + startMarkerName + ", " + endMarkerName);
|
||||
throw new Error(`Failure between markers: '${startMarkerName}', '${endMarkerName}'`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -638,7 +638,6 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public verifyCompletionListAllowsNewIdentifier(negative: boolean) {
|
||||
const completions = this.getCompletionListAtCaret();
|
||||
|
||||
@@ -1479,7 +1478,7 @@ namespace FourSlash {
|
||||
if (isFormattingEdit) {
|
||||
const newContent = this.getFileContent(fileName);
|
||||
|
||||
if (newContent.replace(/\s/g, "") !== oldContent.replace(/\s/g, "")) {
|
||||
if (this.removeWhitespace(newContent) !== this.removeWhitespace(oldContent)) {
|
||||
this.raiseError("Formatting operation destroyed non-whitespace content");
|
||||
}
|
||||
}
|
||||
@@ -1545,6 +1544,10 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
private removeWhitespace(text: string): string {
|
||||
return text.replace(/\s/g, "");
|
||||
}
|
||||
|
||||
public goToBOF() {
|
||||
this.goToPosition(0);
|
||||
}
|
||||
@@ -1862,6 +1865,44 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifyCodeFixAtPosition(expectedText: string, errorCode?: number) {
|
||||
|
||||
const ranges = this.getRanges();
|
||||
if (ranges.length == 0) {
|
||||
this.raiseError("At least one range should be specified in the testfile.");
|
||||
}
|
||||
|
||||
const fileName = this.activeFile.fileName;
|
||||
const diagnostics = this.getDiagnostics(fileName);
|
||||
|
||||
if (diagnostics.length === 0) {
|
||||
this.raiseError("Errors expected.");
|
||||
}
|
||||
|
||||
if (diagnostics.length > 1 && !errorCode) {
|
||||
this.raiseError("When there's more than one error, you must specify the errror to fix.");
|
||||
}
|
||||
|
||||
const diagnostic = !errorCode ? diagnostics[0] : ts.firstOrUndefined(diagnostics, d => d.code == errorCode);
|
||||
|
||||
const actual = this.languageService.getCodeFixesAtPosition(fileName, diagnostic.start, diagnostic.length, [`TS${diagnostic.code}`]);
|
||||
|
||||
if (!actual || actual.length == 0) {
|
||||
this.raiseError("No codefixes returned.");
|
||||
}
|
||||
|
||||
if (actual.length > 1) {
|
||||
this.raiseError("More than 1 codefix returned.");
|
||||
}
|
||||
|
||||
this.applyEdits(actual[0].changes[0].fileName, actual[0].changes[0].textChanges, /*isFormattingEdit*/ false);
|
||||
const actualText = this.rangeText(ranges[0]);
|
||||
|
||||
if (this.removeWhitespace(actualText) !== this.removeWhitespace(expectedText)) {
|
||||
this.raiseError(`Actual text doesn't match expected text. Actual: '${actualText}' Expected: '${expectedText}'`);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyDocCommentTemplate(expected?: ts.TextInsertion) {
|
||||
const name = "verifyDocCommentTemplate";
|
||||
const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition);
|
||||
@@ -3066,6 +3107,10 @@ namespace FourSlashInterface {
|
||||
this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true);
|
||||
}
|
||||
|
||||
public codeFixAtPosition(expectedText: string, errorCode?: number): void {
|
||||
this.state.verifyCodeFixAtPosition(expectedText, errorCode);
|
||||
}
|
||||
|
||||
public navigationBar(json: any) {
|
||||
this.state.verifyNavigationBar(json);
|
||||
}
|
||||
|
||||
@@ -453,6 +453,9 @@ namespace Harness.LanguageService {
|
||||
isValidBraceCompletionAtPosition(fileName: string, position: number, openingBrace: number): boolean {
|
||||
return unwrapJSONCallResult(this.shim.isValidBraceCompletionAtPosition(fileName, position, openingBrace));
|
||||
}
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: string[]): ts.CodeAction[] {
|
||||
return unwrapJSONCallResult(this.shim.getCodeFixesAtPosition(fileName, start, end, JSON.stringify(errorCodes)));
|
||||
}
|
||||
getEmitOutput(fileName: string): ts.EmitOutput {
|
||||
return unwrapJSONCallResult(this.shim.getEmitOutput(fileName));
|
||||
}
|
||||
|
||||
@@ -592,6 +592,10 @@ namespace ts.server {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getCodeFixesAtPosition(fileName: string, start: number, end: number, errorCodes: string[]): ts.CodeAction[] {
|
||||
throw new Error("Not Implemented Yet.");
|
||||
}
|
||||
|
||||
getBraceMatchingAtPosition(fileName: string, position: number): TextSpan[] {
|
||||
const lineOffset = this.positionToOneBasedLineOffset(fileName, position);
|
||||
const args: protocol.FileLocationRequestArgs = {
|
||||
|
||||
@@ -192,6 +192,7 @@ declare namespace FourSlashInterface {
|
||||
noMatchingBracePositionInCurrentFile(bracePosition: number): void;
|
||||
DocCommentTemplate(expectedText: string, expectedOffset: number, empty?: boolean): void;
|
||||
noDocCommentTemplate(): void;
|
||||
codeFixAtPosition(expectedText: string, errorCode?: number): void;
|
||||
|
||||
navigationBar(json: any): void;
|
||||
navigationItemsListCount(count: number, searchValue: string, matchKind?: string): void;
|
||||
|
||||
Reference in New Issue
Block a user