1namespace FourSlashInterface { 2 export class Test { 3 constructor(private state: FourSlash.TestState) { 4 } 5 6 public markers(): FourSlash.Marker[] { 7 return this.state.getMarkers(); 8 } 9 10 public markerNames(): string[] { 11 return this.state.getMarkerNames(); 12 } 13 14 public marker(name: string): FourSlash.Marker { 15 return this.state.getMarkerByName(name); 16 } 17 18 public markerName(m: FourSlash.Marker) { 19 return this.state.markerName(m); 20 } 21 22 public ranges(): FourSlash.Range[] { 23 return this.state.getRanges(); 24 } 25 26 public spans(): ts.TextSpan[] { 27 return this.ranges().map(r => ts.createTextSpan(r.pos, r.end - r.pos)); 28 } 29 30 public rangesByText(): ts.ESMap<string, FourSlash.Range[]> { 31 return this.state.rangesByText(); 32 } 33 34 public markerByName(s: string): FourSlash.Marker { 35 return this.state.getMarkerByName(s); 36 } 37 38 public symbolsInScope(range: FourSlash.Range): ts.Symbol[] { 39 return this.state.symbolsInScope(range); 40 } 41 42 public setTypesRegistry(map: ts.MapLike<void>): void { 43 this.state.setTypesRegistry(map); 44 } 45 } 46 47 export class Plugins { 48 constructor(private state: FourSlash.TestState) { 49 } 50 51 public configurePlugin(pluginName: string, configuration: any): void { 52 this.state.configurePlugin(pluginName, configuration); 53 } 54 } 55 56 export class GoTo { 57 constructor(private state: FourSlash.TestState) { 58 } 59 // Moves the caret to the specified marker, 60 // or the anonymous marker ('/**/') if no name 61 // is given 62 public marker(name?: string | FourSlash.Marker) { 63 this.state.goToMarker(name); 64 } 65 66 public eachMarker(markers: readonly string[], action: (marker: FourSlash.Marker, index: number) => void): void; 67 public eachMarker(action: (marker: FourSlash.Marker, index: number) => void): void; 68 public eachMarker(a: readonly string[] | ((marker: FourSlash.Marker, index: number) => void), b?: (marker: FourSlash.Marker, index: number) => void): void { 69 const markers = typeof a === "function" ? this.state.getMarkers() : a.map(m => this.state.getMarkerByName(m)); 70 this.state.goToEachMarker(markers, typeof a === "function" ? a : b!); 71 } 72 73 74 public rangeStart(range: FourSlash.Range) { 75 this.state.goToRangeStart(range); 76 } 77 78 public eachRange(action: (range: FourSlash.Range) => void) { 79 this.state.goToEachRange(action); 80 } 81 82 public bof() { 83 this.state.goToBOF(); 84 } 85 86 public eof() { 87 this.state.goToEOF(); 88 } 89 90 public implementation() { 91 this.state.goToImplementation(); 92 } 93 94 public position(positionOrLineAndCharacter: number | ts.LineAndCharacter, fileNameOrIndex?: string | number): void { 95 if (fileNameOrIndex !== undefined) { 96 this.file(fileNameOrIndex); 97 } 98 this.state.goToPosition(positionOrLineAndCharacter); 99 } 100 101 // Opens a file, given either its index as it 102 // appears in the test source, or its filename 103 // as specified in the test metadata 104 public file(indexOrName: number | string, content?: string, scriptKindName?: string): void { 105 this.state.openFile(indexOrName, content, scriptKindName); 106 } 107 108 public select(startMarker: string, endMarker: string) { 109 this.state.select(startMarker, endMarker); 110 } 111 112 public selectAllInFile(fileName: string) { 113 this.state.selectAllInFile(fileName); 114 } 115 116 public selectRange(range: FourSlash.Range): void { 117 this.state.selectRange(range); 118 } 119 } 120 121 export class VerifyNegatable { 122 public not: VerifyNegatable | undefined; 123 124 constructor(protected state: FourSlash.TestState, private negative = false) { 125 if (!negative) { 126 this.not = new VerifyNegatable(state, true); 127 } 128 } 129 130 public assertHasRanges(ranges: FourSlash.Range[]) { 131 assert(ranges.length !== 0, "Array of ranges is expected to be non-empty"); 132 } 133 134 public noSignatureHelp(...markers: (string | FourSlash.Marker)[]): void { 135 this.state.verifySignatureHelpPresence(/*expectPresent*/ false, /*triggerReason*/ undefined, markers); 136 } 137 138 public noSignatureHelpForTriggerReason(reason: ts.SignatureHelpTriggerReason, ...markers: (string | FourSlash.Marker)[]): void { 139 this.state.verifySignatureHelpPresence(/*expectPresent*/ false, reason, markers); 140 } 141 142 public signatureHelpPresentForTriggerReason(reason: ts.SignatureHelpTriggerReason, ...markers: (string | FourSlash.Marker)[]): void { 143 this.state.verifySignatureHelpPresence(/*expectPresent*/ true, reason, markers); 144 } 145 146 public signatureHelp(...options: VerifySignatureHelpOptions[]): void { 147 this.state.verifySignatureHelp(options); 148 } 149 150 public errorExistsBetweenMarkers(startMarker: string, endMarker: string) { 151 this.state.verifyErrorExistsBetweenMarkers(startMarker, endMarker, !this.negative); 152 } 153 154 public errorExistsAfterMarker(markerName = "") { 155 this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ true); 156 } 157 158 public errorExistsBeforeMarker(markerName = "") { 159 this.state.verifyErrorExistsAfterMarker(markerName, !this.negative, /*after*/ false); 160 } 161 162 public quickInfoExists() { 163 this.state.verifyQuickInfoExists(this.negative); 164 } 165 166 public typeDefinitionCountIs(expectedCount: number) { 167 this.state.verifyTypeDefinitionsCount(this.negative, expectedCount); 168 } 169 170 public implementationListIsEmpty() { 171 this.state.verifyImplementationListIsEmpty(this.negative); 172 } 173 174 public isValidBraceCompletionAtPosition(openingBrace: string) { 175 this.state.verifyBraceCompletionAtPosition(this.negative, openingBrace); 176 } 177 178 public jsxClosingTag(map: { [markerName: string]: ts.JsxClosingTagInfo | undefined }): void { 179 this.state.verifyJsxClosingTag(map); 180 } 181 182 public isInCommentAtPosition(onlyMultiLineDiverges?: boolean) { 183 this.state.verifySpanOfEnclosingComment(this.negative, onlyMultiLineDiverges); 184 } 185 186 public codeFix(options: VerifyCodeFixOptions) { 187 this.state.verifyCodeFix(options); 188 } 189 190 public codeFixAvailable(options?: VerifyCodeFixAvailableOptions[]) { 191 this.state.verifyCodeFixAvailable(this.negative, options); 192 } 193 194 public codeFixAllAvailable(fixName: string) { 195 this.state.verifyCodeFixAllAvailable(this.negative, fixName); 196 } 197 198 public applicableRefactorAvailableAtMarker(markerName: string) { 199 this.state.verifyApplicableRefactorAvailableAtMarker(this.negative, markerName); 200 } 201 202 public applicableRefactorAvailableForRange() { 203 this.state.verifyApplicableRefactorAvailableForRange(this.negative); 204 } 205 206 public refactorsAvailable(names: readonly string[]): void { 207 this.state.verifyRefactorsAvailable(names); 208 } 209 210 public refactorAvailable(name: string, actionName?: string) { 211 this.state.verifyRefactorAvailable(this.negative, "implicit", name, actionName); 212 } 213 214 public refactorAvailableForTriggerReason(triggerReason: ts.RefactorTriggerReason, name: string, actionName?: string) { 215 this.state.verifyRefactorAvailable(this.negative, triggerReason, name, actionName); 216 } 217 218 public refactorKindAvailable(kind: string, expected: string[], preferences = ts.emptyOptions) { 219 this.state.verifyRefactorKindsAvailable(kind, expected, preferences); 220 } 221 222 public toggleLineComment(newFileContent: string) { 223 this.state.toggleLineComment(newFileContent); 224 } 225 226 public toggleMultilineComment(newFileContent: string) { 227 this.state.toggleMultilineComment(newFileContent); 228 } 229 230 public commentSelection(newFileContent: string) { 231 this.state.commentSelection(newFileContent); 232 } 233 234 public uncommentSelection(newFileContent: string) { 235 this.state.uncommentSelection(newFileContent); 236 } 237 } 238 239 export class Verify extends VerifyNegatable { 240 constructor(state: FourSlash.TestState) { 241 super(state); 242 } 243 244 public completions(...optionsArray: VerifyCompletionsOptions[]) { 245 for (const options of optionsArray) { 246 this.state.verifyCompletions(options); 247 } 248 } 249 250 public quickInfoIs(expectedText: string, expectedDocumentation?: string) { 251 this.state.verifyQuickInfoString(expectedText, expectedDocumentation); 252 } 253 254 public quickInfoAt(markerName: string | FourSlash.Range, expectedText: string, expectedDocumentation?: string) { 255 this.state.verifyQuickInfoAt(markerName, expectedText, expectedDocumentation); 256 } 257 258 public quickInfos(namesAndTexts: { [name: string]: string }) { 259 this.state.verifyQuickInfos(namesAndTexts); 260 } 261 262 public caretAtMarker(markerName?: string) { 263 this.state.verifyCaretAtMarker(markerName); 264 } 265 266 public indentationIs(numberOfSpaces: number) { 267 this.state.verifyIndentationAtCurrentPosition(numberOfSpaces); 268 } 269 270 public indentationAtPositionIs(fileName: string, position: number, numberOfSpaces: number, indentStyle = ts.IndentStyle.Smart, baseIndentSize = 0) { 271 this.state.verifyIndentationAtPosition(fileName, position, numberOfSpaces, indentStyle, baseIndentSize); 272 } 273 274 public textAtCaretIs(text: string) { 275 this.state.verifyTextAtCaretIs(text); 276 } 277 278 /** 279 * Compiles the current file and evaluates 'expr' in a context containing 280 * the emitted output, then compares (using ===) the result of that expression 281 * to 'value'. Do not use this function with external modules as it is not supported. 282 */ 283 public eval(expr: string, value: any) { 284 this.state.verifyEval(expr, value); 285 } 286 287 public currentLineContentIs(text: string) { 288 this.state.verifyCurrentLineContent(text); 289 } 290 291 public currentFileContentIs(text: string) { 292 this.state.verifyCurrentFileContent(text); 293 } 294 295 public formatDocumentChangesNothing(): void { 296 this.state.verifyFormatDocumentChangesNothing(); 297 } 298 299 public goToDefinitionIs(endMarkers: ArrayOrSingle<string>) { 300 this.state.verifyGoToDefinitionIs(endMarkers); 301 } 302 303 public goToDefinition(startMarkerName: ArrayOrSingle<string>, endMarkerName: ArrayOrSingle<string>, range?: FourSlash.Range): void; 304 public goToDefinition(startsAndEnds: [ArrayOrSingle<string>, ArrayOrSingle<string>][] | { [startMarkerName: string]: ArrayOrSingle<string> }): void; 305 public goToDefinition(arg0: any, endMarkerName?: ArrayOrSingle<string>) { 306 this.state.verifyGoToDefinition(arg0, endMarkerName); 307 } 308 309 public goToType(startMarkerName: ArrayOrSingle<string>, endMarkerName: ArrayOrSingle<string>): void; 310 public goToType(startsAndEnds: [ArrayOrSingle<string>, ArrayOrSingle<string>][] | { [startMarkerName: string]: ArrayOrSingle<string> }): void; 311 public goToType(arg0: any, endMarkerName?: ArrayOrSingle<string>) { 312 this.state.verifyGoToType(arg0, endMarkerName); 313 } 314 315 public goToDefinitionForMarkers(...markerNames: string[]) { 316 this.state.verifyGoToDefinitionForMarkers(markerNames); 317 } 318 319 public goToDefinitionName(name: string, containerName: string) { 320 this.state.verifyGoToDefinitionName(name, containerName); 321 } 322 323 public verifyGetEmitOutputForCurrentFile(expected: string): void { 324 this.state.verifyGetEmitOutputForCurrentFile(expected); 325 } 326 327 public verifyGetEmitOutputContentsForCurrentFile(expected: ts.OutputFile[]): void { 328 this.state.verifyGetEmitOutputContentsForCurrentFile(expected); 329 } 330 331 public symbolAtLocation(startRange: FourSlash.Range, ...declarationRanges: FourSlash.Range[]) { 332 this.state.verifySymbolAtLocation(startRange, declarationRanges); 333 } 334 335 public typeOfSymbolAtLocation(range: FourSlash.Range, symbol: ts.Symbol, expected: string) { 336 this.state.verifyTypeOfSymbolAtLocation(range, symbol, expected); 337 } 338 339 public baselineFindAllReferences(...markerNames: string[]) { 340 this.state.verifyBaselineFindAllReferences(...markerNames); 341 } 342 343 public baselineGetFileReferences(fileName: string) { 344 this.state.verifyBaselineGetFileReferences(fileName); 345 } 346 347 public referenceGroups(starts: ArrayOrSingle<string> | ArrayOrSingle<FourSlash.Range>, parts: ReferenceGroup[]) { 348 this.state.verifyReferenceGroups(starts, parts); 349 } 350 351 public noReferences(markerNameOrRange?: string | FourSlash.Range) { 352 this.state.verifyNoReferences(markerNameOrRange); 353 } 354 355 public getReferencesForServerTest(expected: readonly ts.ReferenceEntry[]) { 356 this.state.verifyGetReferencesForServerTest(expected); 357 } 358 359 public singleReferenceGroup(definition: ReferenceGroupDefinition, ranges?: FourSlash.Range[] | string) { 360 this.state.verifySingleReferenceGroup(definition, ranges); 361 } 362 363 public findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]) { 364 this.state.verifyDisplayPartsOfReferencedSymbol(expected); 365 } 366 367 public noErrors() { 368 this.state.verifyNoErrors(); 369 } 370 371 public errorExistsAtRange(range: FourSlash.Range, code: number, message?: string) { 372 this.state.verifyErrorExistsAtRange(range, code, message); 373 } 374 375 public numberOfErrorsInCurrentFile(expected: number) { 376 this.state.verifyNumberOfErrorsInCurrentFile(expected); 377 } 378 379 public baselineCurrentFileBreakpointLocations() { 380 this.state.baselineCurrentFileBreakpointLocations(); 381 } 382 383 public baselineCurrentFileNameOrDottedNameSpans() { 384 this.state.baselineCurrentFileNameOrDottedNameSpans(); 385 } 386 387 public getEmitOutput(expectedOutputFiles: readonly string[]): void { 388 this.state.verifyGetEmitOutput(expectedOutputFiles); 389 } 390 391 public baselineGetEmitOutput() { 392 this.state.baselineGetEmitOutput(); 393 } 394 395 public baselineQuickInfo() { 396 this.state.baselineQuickInfo(); 397 } 398 399 public baselineSmartSelection() { 400 this.state.baselineSmartSelection(); 401 } 402 403 public baselineSyntacticDiagnostics() { 404 this.state.baselineSyntacticDiagnostics(); 405 } 406 407 public baselineSyntacticAndSemanticDiagnostics() { 408 this.state.baselineSyntacticAndSemanticDiagnostics(); 409 } 410 411 public nameOrDottedNameSpanTextIs(text: string) { 412 this.state.verifyCurrentNameOrDottedNameSpanText(text); 413 } 414 415 public outliningSpansInCurrentFile(spans: FourSlash.Range[], kind?: "comment" | "region" | "code" | "imports") { 416 this.state.verifyOutliningSpans(spans, kind); 417 } 418 419 public outliningHintSpansInCurrentFile(spans: FourSlash.Range[]) { 420 this.state.verifyOutliningHintSpans(spans); 421 } 422 423 public todoCommentsInCurrentFile(descriptors: string[]) { 424 this.state.verifyTodoComments(descriptors, this.state.getRanges()); 425 } 426 427 public matchingBracePositionInCurrentFile(bracePosition: number, expectedMatchPosition: number) { 428 this.state.verifyMatchingBracePosition(bracePosition, expectedMatchPosition); 429 } 430 431 public noMatchingBracePositionInCurrentFile(bracePosition: number) { 432 this.state.verifyNoMatchingBracePosition(bracePosition); 433 } 434 435 public docCommentTemplateAt(marker: string | FourSlash.Marker, expectedOffset: number, expectedText: string, options?: ts.DocCommentTemplateOptions) { 436 this.state.goToMarker(marker); 437 this.state.verifyDocCommentTemplate({ newText: expectedText.replace(/\r?\n/g, "\r\n"), caretOffset: expectedOffset }, options); 438 } 439 440 public noDocCommentTemplateAt(marker: string | FourSlash.Marker) { 441 this.state.goToMarker(marker); 442 this.state.verifyDocCommentTemplate(/*expected*/ undefined); 443 } 444 445 public rangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number): void { 446 this.state.verifyRangeAfterCodeFix(expectedText, includeWhiteSpace, errorCode, index); 447 } 448 449 public codeFixAll(options: VerifyCodeFixAllOptions): void { 450 this.state.verifyCodeFixAll(options); 451 } 452 453 public fileAfterApplyingRefactorAtMarker(markerName: string, expectedContent: string, refactorNameToApply: string, actionName: string, formattingOptions?: ts.FormatCodeSettings): void { 454 this.state.verifyFileAfterApplyingRefactorAtMarker(markerName, expectedContent, refactorNameToApply, actionName, formattingOptions); 455 } 456 457 public rangeIs(expectedText: string, includeWhiteSpace?: boolean): void { 458 this.state.verifyRangeIs(expectedText, includeWhiteSpace); 459 } 460 461 public getAndApplyCodeFix(errorCode?: number, index?: number): void { 462 this.state.getAndApplyCodeActions(errorCode, index); 463 } 464 465 public applyCodeActionFromCompletion(markerName: string, options: VerifyCompletionActionOptions): void { 466 this.state.applyCodeActionFromCompletion(markerName, options); 467 } 468 469 public importFixAtPosition(expectedTextArray: string[], errorCode?: number, preferences?: ts.UserPreferences): void { 470 this.state.verifyImportFixAtPosition(expectedTextArray, errorCode, preferences); 471 } 472 473 public importFixModuleSpecifiers(marker: string, moduleSpecifiers: string[]) { 474 this.state.verifyImportFixModuleSpecifiers(marker, moduleSpecifiers); 475 } 476 477 public navigationBar(json: any, options?: { checkSpans?: boolean }) { 478 this.state.verifyNavigationBar(json, options); 479 } 480 481 public navigationTree(json: any, options?: { checkSpans?: boolean }) { 482 this.state.verifyNavigationTree(json, options); 483 } 484 485 public navigateTo(...options: VerifyNavigateToOptions[]): void { 486 this.state.verifyNavigateTo(options); 487 } 488 489 public occurrencesAtPositionContains(range: FourSlash.Range, isWriteAccess?: boolean) { 490 this.state.verifyOccurrencesAtPositionListContains(range.fileName, range.pos, range.end, isWriteAccess); 491 } 492 493 public occurrencesAtPositionCount(expectedCount: number) { 494 this.state.verifyOccurrencesAtPositionListCount(expectedCount); 495 } 496 497 public rangesAreOccurrences(isWriteAccess?: boolean, ranges?: FourSlash.Range[]) { 498 this.state.verifyRangesAreOccurrences(isWriteAccess, ranges); 499 } 500 501 public rangesWithSameTextAreRenameLocations(...texts: string[]) { 502 this.state.verifyRangesWithSameTextAreRenameLocations(...texts); 503 } 504 505 public rangesAreRenameLocations(options?: FourSlash.Range[] | { findInStrings?: boolean, findInComments?: boolean, ranges?: FourSlash.Range[], providePrefixAndSuffixTextForRename?: boolean }) { 506 this.state.verifyRangesAreRenameLocations(options); 507 } 508 509 public rangesAreDocumentHighlights(ranges?: FourSlash.Range[], options?: VerifyDocumentHighlightsOptions) { 510 this.state.verifyRangesAreDocumentHighlights(ranges, options); 511 } 512 513 public rangesWithSameTextAreDocumentHighlights() { 514 this.state.verifyRangesWithSameTextAreDocumentHighlights(); 515 } 516 517 public documentHighlightsOf(startRange: FourSlash.Range, ranges: FourSlash.Range[], options?: VerifyDocumentHighlightsOptions) { 518 this.state.verifyDocumentHighlightsOf(startRange, ranges, options); 519 } 520 521 public noDocumentHighlights(startRange: FourSlash.Range) { 522 this.state.verifyNoDocumentHighlights(startRange); 523 } 524 525 /** 526 * This method *requires* a contiguous, complete, and ordered stream of classifications for a file. 527 */ 528 public syntacticClassificationsAre(...classifications: { classificationType: string; text: string }[]) { 529 this.state.verifySyntacticClassifications(classifications); 530 } 531 532 /** 533 * This method *requires* an ordered stream of classifications for a file, and spans are highly recommended. 534 */ 535 public semanticClassificationsAre(format: ts.SemanticClassificationFormat, ...classifications: Classification[]) { 536 this.state.verifySemanticClassifications(format, classifications); 537 } 538 539 public replaceWithSemanticClassifications(format: ts.SemanticClassificationFormat.TwentyTwenty) { 540 this.state.replaceWithSemanticClassifications(format); 541 } 542 543 public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string, fileToRename?: string, expectedRange?: FourSlash.Range, options?: ts.RenameInfoOptions) { 544 this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers, fileToRename, expectedRange, options); 545 } 546 547 public renameInfoFailed(message?: string, allowRenameOfImportPath?: boolean) { 548 this.state.verifyRenameInfoFailed(message, allowRenameOfImportPath); 549 } 550 551 public renameLocations(startRanges: ArrayOrSingle<FourSlash.Range>, options: RenameLocationsOptions) { 552 this.state.verifyRenameLocations(startRanges, options); 553 } 554 555 public baselineRename(marker: string, options: RenameOptions) { 556 this.state.baselineRename(marker, options); 557 } 558 559 public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: FourSlash.TextSpan, 560 displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[], tags: ts.JSDocTagInfo[]) { 561 this.state.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation, tags); 562 } 563 564 public getSyntacticDiagnostics(expected: readonly Diagnostic[]) { 565 this.state.getSyntacticDiagnostics(expected); 566 } 567 568 public getSemanticDiagnostics(expected: readonly Diagnostic[]) { 569 this.state.getSemanticDiagnostics(expected); 570 } 571 572 public getSuggestionDiagnostics(expected: readonly Diagnostic[]) { 573 this.state.getSuggestionDiagnostics(expected); 574 } 575 576 public ProjectInfo(expected: string[]) { 577 this.state.verifyProjectInfo(expected); 578 } 579 580 public allRangesAppearInImplementationList(markerName: string) { 581 this.state.verifyRangesInImplementationList(markerName); 582 } 583 584 public getEditsForFileRename(options: GetEditsForFileRenameOptions) { 585 this.state.getEditsForFileRename(options); 586 } 587 588 public baselineCallHierarchy() { 589 this.state.baselineCallHierarchy(); 590 } 591 592 public moveToNewFile(options: MoveToNewFileOptions): void { 593 this.state.moveToNewFile(options); 594 } 595 596 public noMoveToNewFile(): void { 597 this.state.noMoveToNewFile(); 598 } 599 600 public organizeImports(newContent: string) { 601 this.state.verifyOrganizeImports(newContent); 602 } 603 } 604 605 export class Edit { 606 constructor(private state: FourSlash.TestState) { 607 } 608 public backspace(count?: number) { 609 this.state.deleteCharBehindMarker(count); 610 } 611 612 public deleteAtCaret(times?: number) { 613 this.state.deleteChar(times); 614 } 615 616 public replace(start: number, length: number, text: string) { 617 this.state.replace(start, length, text); 618 } 619 620 public paste(text: string) { 621 this.state.paste(text); 622 } 623 624 public insert(text: string) { 625 this.insertLines(text); 626 } 627 628 public insertLine(text: string) { 629 this.insertLines(text + "\n"); 630 } 631 632 public insertLines(...lines: string[]) { 633 this.state.type(lines.join("\n")); 634 } 635 636 public deleteLine(index: number) { 637 this.deleteLineRange(index, index); 638 } 639 640 public deleteLineRange(startIndex: number, endIndexInclusive: number) { 641 this.state.deleteLineRange(startIndex, endIndexInclusive); 642 } 643 644 public replaceLine(index: number, text: string) { 645 this.state.selectLine(index); 646 this.state.type(text); 647 } 648 649 public moveRight(count?: number) { 650 this.state.moveCaretRight(count); 651 } 652 653 public moveLeft(count?: number) { 654 if (typeof count === "undefined") { 655 count = 1; 656 } 657 this.state.moveCaretRight(count * -1); 658 } 659 660 public enableFormatting() { 661 this.state.enableFormatting = true; 662 } 663 664 public disableFormatting() { 665 this.state.enableFormatting = false; 666 } 667 668 public applyRefactor(options: ApplyRefactorOptions) { 669 this.state.applyRefactor(options); 670 } 671 } 672 673 export class Debug { 674 constructor(private state: FourSlash.TestState) { 675 } 676 677 public printCurrentParameterHelp() { 678 this.state.printCurrentParameterHelp(); 679 } 680 681 public printCurrentFileState() { 682 this.state.printCurrentFileState(/*showWhitespace*/ false, /*makeCaretVisible*/ true); 683 } 684 685 public printCurrentFileStateWithWhitespace() { 686 this.state.printCurrentFileState(/*showWhitespace*/ true, /*makeCaretVisible*/ true); 687 } 688 689 public printCurrentFileStateWithoutCaret() { 690 this.state.printCurrentFileState(/*showWhitespace*/ false, /*makeCaretVisible*/ false); 691 } 692 693 public printCurrentQuickInfo() { 694 this.state.printCurrentQuickInfo(); 695 } 696 697 public printCurrentSignatureHelp() { 698 this.state.printCurrentSignatureHelp(); 699 } 700 701 public printCompletionListMembers(options: ts.UserPreferences | undefined) { 702 this.state.printCompletionListMembers(options); 703 } 704 705 public printAvailableCodeFixes() { 706 this.state.printAvailableCodeFixes(); 707 } 708 709 public printBreakpointLocation(pos: number) { 710 this.state.printBreakpointLocation(pos); 711 } 712 public printBreakpointAtCurrentLocation() { 713 this.state.printBreakpointAtCurrentLocation(); 714 } 715 716 public printNameOrDottedNameSpans(pos: number) { 717 this.state.printNameOrDottedNameSpans(pos); 718 } 719 720 public printErrorList() { 721 this.state.printErrorList(); 722 } 723 724 public printNavigationItems(searchValue = ".*") { 725 this.state.printNavigationItems(searchValue); 726 } 727 728 public printNavigationBar() { 729 this.state.printNavigationBar(); 730 } 731 732 public printContext() { 733 this.state.printContext(); 734 } 735 736 public printOutliningSpans() { 737 this.state.printOutliningSpans(); 738 } 739 } 740 741 export class Format { 742 constructor(private state: FourSlash.TestState) { 743 } 744 745 public document() { 746 this.state.formatDocument(); 747 } 748 749 public copyFormatOptions(): ts.FormatCodeSettings { 750 return this.state.copyFormatOptions(); 751 } 752 753 public setFormatOptions(options: ts.FormatCodeOptions) { 754 return this.state.setFormatOptions(options); 755 } 756 757 public selection(startMarker: string, endMarker: string) { 758 this.state.formatSelection(this.state.getMarkerByName(startMarker).position, this.state.getMarkerByName(endMarker).position); 759 } 760 761 public onType(posMarker: string, key: string) { 762 this.state.formatOnType(this.state.getMarkerByName(posMarker).position, key); 763 } 764 765 public setOption(name: keyof ts.FormatCodeSettings, value: number | string | boolean): void { 766 this.state.setFormatOptions({ ...this.state.formatCodeSettings, [name]: value }); 767 } 768 } 769 770 export class Cancellation { 771 constructor(private state: FourSlash.TestState) { 772 } 773 774 public resetCancelled() { 775 this.state.resetCancelled(); 776 } 777 778 public setCancelled(numberOfCalls = 0) { 779 this.state.setCancelled(numberOfCalls); 780 } 781 } 782 783 interface OlderClassification { 784 classificationType: ts.ClassificationTypeNames; 785 text: string; 786 textSpan?: FourSlash.TextSpan; 787 } 788 789 // The VS Code LSP 790 interface ModernClassification { 791 classificationType: string; 792 text?: string; 793 textSpan?: FourSlash.TextSpan; 794 } 795 796 type Classification = OlderClassification | ModernClassification; 797 798 export function classification(format: ts.SemanticClassificationFormat) { 799 800 function semanticToken(identifier: string, text: string, _position: number): Classification { 801 return { 802 classificationType: identifier, 803 text 804 }; 805 } 806 807 if (format === ts.SemanticClassificationFormat.TwentyTwenty) { 808 return { 809 semanticToken 810 }; 811 } 812 813 // Defaults to the previous semantic classifier factory functions 814 815 function comment(text: string, position?: number): Classification { 816 return getClassification(ts.ClassificationTypeNames.comment, text, position); 817 } 818 819 function identifier(text: string, position?: number): Classification { 820 return getClassification(ts.ClassificationTypeNames.identifier, text, position); 821 } 822 823 function keyword(text: string, position?: number): Classification { 824 return getClassification(ts.ClassificationTypeNames.keyword, text, position); 825 } 826 827 function numericLiteral(text: string, position?: number): Classification { 828 return getClassification(ts.ClassificationTypeNames.numericLiteral, text, position); 829 } 830 831 function operator(text: string, position?: number): Classification { 832 return getClassification(ts.ClassificationTypeNames.operator, text, position); 833 } 834 835 function stringLiteral(text: string, position?: number): Classification { 836 return getClassification(ts.ClassificationTypeNames.stringLiteral, text, position); 837 } 838 839 function whiteSpace(text: string, position?: number): Classification { 840 return getClassification(ts.ClassificationTypeNames.whiteSpace, text, position); 841 } 842 843 function text(text: string, position?: number): Classification { 844 return getClassification(ts.ClassificationTypeNames.text, text, position); 845 } 846 847 function punctuation(text: string, position?: number): Classification { 848 return getClassification(ts.ClassificationTypeNames.punctuation, text, position); 849 } 850 851 function docCommentTagName(text: string, position?: number): Classification { 852 return getClassification(ts.ClassificationTypeNames.docCommentTagName, text, position); 853 } 854 855 function className(text: string, position?: number): Classification { 856 return getClassification(ts.ClassificationTypeNames.className, text, position); 857 } 858 859 function enumName(text: string, position?: number): Classification { 860 return getClassification(ts.ClassificationTypeNames.enumName, text, position); 861 } 862 863 function interfaceName(text: string, position?: number): Classification { 864 return getClassification(ts.ClassificationTypeNames.interfaceName, text, position); 865 } 866 867 function moduleName(text: string, position?: number): Classification { 868 return getClassification(ts.ClassificationTypeNames.moduleName, text, position); 869 } 870 871 function typeParameterName(text: string, position?: number): Classification { 872 return getClassification(ts.ClassificationTypeNames.typeParameterName, text, position); 873 } 874 875 function parameterName(text: string, position?: number): Classification { 876 return getClassification(ts.ClassificationTypeNames.parameterName, text, position); 877 } 878 879 function typeAliasName(text: string, position?: number): Classification { 880 return getClassification(ts.ClassificationTypeNames.typeAliasName, text, position); 881 } 882 883 function jsxOpenTagName(text: string, position?: number): Classification { 884 return getClassification(ts.ClassificationTypeNames.jsxOpenTagName, text, position); 885 } 886 887 function jsxCloseTagName(text: string, position?: number): Classification { 888 return getClassification(ts.ClassificationTypeNames.jsxCloseTagName, text, position); 889 } 890 891 function jsxSelfClosingTagName(text: string, position?: number): Classification { 892 return getClassification(ts.ClassificationTypeNames.jsxSelfClosingTagName, text, position); 893 } 894 895 function jsxAttribute(text: string, position?: number): Classification { 896 return getClassification(ts.ClassificationTypeNames.jsxAttribute, text, position); 897 } 898 899 function jsxText(text: string, position?: number): Classification { 900 return getClassification(ts.ClassificationTypeNames.jsxText, text, position); 901 } 902 903 function jsxAttributeStringLiteralValue(text: string, position?: number): Classification { 904 return getClassification(ts.ClassificationTypeNames.jsxAttributeStringLiteralValue, text, position); 905 } 906 907 function getClassification(classificationType: ts.ClassificationTypeNames, text: string, position?: number): Classification { 908 const textSpan = position === undefined ? undefined : { start: position, end: position + text.length }; 909 return { classificationType, text, textSpan }; 910 } 911 912 return { 913 comment, 914 identifier, 915 keyword, 916 numericLiteral, 917 operator, 918 stringLiteral, 919 whiteSpace, 920 text, 921 punctuation, 922 docCommentTagName, 923 className, 924 enumName, 925 interfaceName, 926 moduleName, 927 typeParameterName, 928 parameterName, 929 typeAliasName, 930 jsxOpenTagName, 931 jsxCloseTagName, 932 jsxSelfClosingTagName, 933 jsxAttribute, 934 jsxText, 935 jsxAttributeStringLiteralValue, 936 getClassification 937 }; 938 } 939 940 export namespace Completion { 941 export import SortText = ts.Completions.SortText; 942 export import CompletionSource = ts.Completions.CompletionSource; 943 944 const functionEntry = (name: string): ExpectedCompletionEntryObject => ({ 945 name, 946 kind: "function", 947 kindModifiers: "declare", 948 sortText: SortText.GlobalsOrKeywords 949 }); 950 const varEntry = (name: string): ExpectedCompletionEntryObject => ({ 951 name, 952 kind: "var", 953 kindModifiers: "declare", 954 sortText: SortText.GlobalsOrKeywords 955 }); 956 const moduleEntry = (name: string): ExpectedCompletionEntryObject => ({ 957 name, 958 kind: "module", 959 kindModifiers: "declare", 960 sortText: SortText.GlobalsOrKeywords 961 }); 962 const keywordEntry = (name: string): ExpectedCompletionEntryObject => ({ 963 name, 964 kind: "keyword", 965 sortText: SortText.GlobalsOrKeywords 966 }); 967 const methodEntry = (name: string): ExpectedCompletionEntryObject => ({ 968 name, 969 kind: "method", 970 kindModifiers: "declare", 971 sortText: SortText.LocationPriority 972 }); 973 const propertyEntry = (name: string): ExpectedCompletionEntryObject => ({ 974 name, 975 kind: "property", 976 kindModifiers: "declare", 977 sortText: SortText.LocationPriority 978 }); 979 const interfaceEntry = (name: string): ExpectedCompletionEntryObject => ({ 980 name, 981 kind: "interface", 982 kindModifiers: "declare", 983 sortText: SortText.GlobalsOrKeywords 984 }); 985 const typeEntry = (name: string): ExpectedCompletionEntryObject => ({ 986 name, 987 kind: "type", 988 kindModifiers: "declare", 989 sortText: SortText.GlobalsOrKeywords 990 }); 991 992 const res: ExpectedCompletionEntryObject[] = []; 993 for (let i = ts.SyntaxKind.FirstKeyword; i <= ts.SyntaxKind.LastKeyword; i++) { 994 res.push({ 995 name: ts.Debug.checkDefined(ts.tokenToString(i)), 996 kind: "keyword", 997 sortText: SortText.GlobalsOrKeywords 998 }); 999 } 1000 export const keywordsWithUndefined: readonly ExpectedCompletionEntryObject[] = res; 1001 export const keywords: readonly ExpectedCompletionEntryObject[] = keywordsWithUndefined.filter(k => k.name !== "undefined"); 1002 1003 export const typeKeywords: readonly ExpectedCompletionEntryObject[] = 1004 ["false", "null", "true", "void", "asserts", "any", "boolean", "infer", "keyof", "never", "readonly", "number", "object", "string", "symbol", "undefined", "unique", "unknown", "bigint"].map(keywordEntry); 1005 1006 const globalTypeDecls: readonly ExpectedCompletionEntryObject[] = [ 1007 interfaceEntry("Symbol"), 1008 typeEntry("PropertyKey"), 1009 interfaceEntry("PropertyDescriptor"), 1010 interfaceEntry("PropertyDescriptorMap"), 1011 varEntry("Object"), 1012 interfaceEntry("ObjectConstructor"), 1013 varEntry("Function"), 1014 interfaceEntry("FunctionConstructor"), 1015 typeEntry("ThisParameterType"), 1016 typeEntry("OmitThisParameter"), 1017 interfaceEntry("CallableFunction"), 1018 interfaceEntry("NewableFunction"), 1019 interfaceEntry("IArguments"), 1020 varEntry("String"), 1021 interfaceEntry("StringConstructor"), 1022 varEntry("Boolean"), 1023 interfaceEntry("BooleanConstructor"), 1024 varEntry("Number"), 1025 interfaceEntry("NumberConstructor"), 1026 interfaceEntry("TemplateStringsArray"), 1027 interfaceEntry("ImportMeta"), 1028 varEntry("Math"), 1029 varEntry("Date"), 1030 interfaceEntry("DateConstructor"), 1031 interfaceEntry("RegExpMatchArray"), 1032 interfaceEntry("RegExpExecArray"), 1033 varEntry("RegExp"), 1034 interfaceEntry("RegExpConstructor"), 1035 varEntry("Error"), 1036 interfaceEntry("ErrorConstructor"), 1037 varEntry("EvalError"), 1038 interfaceEntry("EvalErrorConstructor"), 1039 varEntry("RangeError"), 1040 interfaceEntry("RangeErrorConstructor"), 1041 varEntry("ReferenceError"), 1042 interfaceEntry("ReferenceErrorConstructor"), 1043 varEntry("SyntaxError"), 1044 interfaceEntry("SyntaxErrorConstructor"), 1045 varEntry("TypeError"), 1046 interfaceEntry("TypeErrorConstructor"), 1047 varEntry("URIError"), 1048 interfaceEntry("URIErrorConstructor"), 1049 varEntry("JSON"), 1050 interfaceEntry("ReadonlyArray"), 1051 interfaceEntry("ConcatArray"), 1052 varEntry("Array"), 1053 interfaceEntry("ArrayConstructor"), 1054 interfaceEntry("TypedPropertyDescriptor"), 1055 typeEntry("ClassDecorator"), 1056 typeEntry("PropertyDecorator"), 1057 typeEntry("MethodDecorator"), 1058 typeEntry("ParameterDecorator"), 1059 typeEntry("PromiseConstructorLike"), 1060 interfaceEntry("PromiseLike"), 1061 interfaceEntry("Promise"), 1062 interfaceEntry("ArrayLike"), 1063 typeEntry("Partial"), 1064 typeEntry("Required"), 1065 typeEntry("Readonly"), 1066 typeEntry("Pick"), 1067 typeEntry("Record"), 1068 typeEntry("Exclude"), 1069 typeEntry("Extract"), 1070 typeEntry("Omit"), 1071 typeEntry("NonNullable"), 1072 typeEntry("Parameters"), 1073 typeEntry("ConstructorParameters"), 1074 typeEntry("ReturnType"), 1075 typeEntry("InstanceType"), 1076 typeEntry("Uppercase"), 1077 typeEntry("Lowercase"), 1078 typeEntry("Capitalize"), 1079 typeEntry("Uncapitalize"), 1080 interfaceEntry("ThisType"), 1081 varEntry("ArrayBuffer"), 1082 interfaceEntry("ArrayBufferTypes"), 1083 typeEntry("ArrayBufferLike"), 1084 interfaceEntry("ArrayBufferConstructor"), 1085 interfaceEntry("ArrayBufferView"), 1086 varEntry("DataView"), 1087 interfaceEntry("DataViewConstructor"), 1088 varEntry("Int8Array"), 1089 interfaceEntry("Int8ArrayConstructor"), 1090 varEntry("Uint8Array"), 1091 interfaceEntry("Uint8ArrayConstructor"), 1092 varEntry("Uint8ClampedArray"), 1093 interfaceEntry("Uint8ClampedArrayConstructor"), 1094 varEntry("Int16Array"), 1095 interfaceEntry("Int16ArrayConstructor"), 1096 varEntry("Uint16Array"), 1097 interfaceEntry("Uint16ArrayConstructor"), 1098 varEntry("Int32Array"), 1099 interfaceEntry("Int32ArrayConstructor"), 1100 varEntry("Uint32Array"), 1101 interfaceEntry("Uint32ArrayConstructor"), 1102 varEntry("Float32Array"), 1103 interfaceEntry("Float32ArrayConstructor"), 1104 varEntry("Float64Array"), 1105 interfaceEntry("Float64ArrayConstructor"), 1106 moduleEntry("Intl"), 1107 typeEntry("ESObject"), 1108 ]; 1109 1110 export const globalThisEntry: ExpectedCompletionEntry = { 1111 name: "globalThis", 1112 kind: "module", 1113 sortText: SortText.GlobalsOrKeywords 1114 }; 1115 export const globalTypes = globalTypesPlus([]); 1116 export function globalTypesPlus(plus: readonly ExpectedCompletionEntry[]): readonly ExpectedCompletionEntry[] { 1117 return [ 1118 globalThisEntry, 1119 ...globalTypeDecls, 1120 ...plus, 1121 ...typeKeywords, 1122 ]; 1123 } 1124 1125 export const typeAssertionKeywords: readonly ExpectedCompletionEntry[] = 1126 globalTypesPlus([keywordEntry("const")]); 1127 1128 function getInJsKeywords(keywords: readonly ExpectedCompletionEntryObject[]): readonly ExpectedCompletionEntryObject[] { 1129 return keywords.filter(keyword => { 1130 switch (keyword.name) { 1131 case "enum": 1132 case "interface": 1133 case "implements": 1134 case "private": 1135 case "protected": 1136 case "public": 1137 case "abstract": 1138 case "any": 1139 case "boolean": 1140 case "declare": 1141 case "infer": 1142 case "is": 1143 case "keyof": 1144 case "module": 1145 case "namespace": 1146 case "never": 1147 case "readonly": 1148 case "number": 1149 case "object": 1150 case "string": 1151 case "symbol": 1152 case "type": 1153 case "unique": 1154 case "unknown": 1155 case "global": 1156 case "bigint": 1157 return false; 1158 default: 1159 return true; 1160 } 1161 }); 1162 } 1163 1164 export const classElementKeywords: readonly ExpectedCompletionEntryObject[] = 1165 ["private", "protected", "public", "static", "abstract", "async", "constructor", "declare", "get", "readonly", "set"].map(keywordEntry); 1166 1167 export const classElementInJsKeywords = getInJsKeywords(classElementKeywords); 1168 1169 export const constructorParameterKeywords: readonly ExpectedCompletionEntryObject[] = 1170 ["private", "protected", "public", "readonly"].map((name): ExpectedCompletionEntryObject => ({ 1171 name, 1172 kind: "keyword", 1173 sortText: SortText.GlobalsOrKeywords 1174 })); 1175 1176 export const functionMembers: readonly ExpectedCompletionEntryObject[] = [ 1177 methodEntry("apply"), 1178 methodEntry("call"), 1179 methodEntry("bind"), 1180 methodEntry("toString"), 1181 propertyEntry("length"), 1182 { name: "arguments", kind: "property", kindModifiers: "declare", text: "(property) Function.arguments: any" }, 1183 propertyEntry("caller"), 1184 ]; 1185 1186 export const stringMembers: readonly ExpectedCompletionEntryObject[] = [ 1187 methodEntry("toString"), 1188 methodEntry("charAt"), 1189 methodEntry("charCodeAt"), 1190 methodEntry("concat"), 1191 methodEntry("indexOf"), 1192 methodEntry("lastIndexOf"), 1193 methodEntry("localeCompare"), 1194 methodEntry("match"), 1195 methodEntry("replace"), 1196 methodEntry("search"), 1197 methodEntry("slice"), 1198 methodEntry("split"), 1199 methodEntry("substring"), 1200 methodEntry("toLowerCase"), 1201 methodEntry("toLocaleLowerCase"), 1202 methodEntry("toUpperCase"), 1203 methodEntry("toLocaleUpperCase"), 1204 methodEntry("trim"), 1205 propertyEntry("length"), 1206 methodEntry("substr"), 1207 methodEntry("valueOf"), 1208 ]; 1209 1210 export const functionMembersWithPrototype: readonly ExpectedCompletionEntryObject[] = [ 1211 ...functionMembers.slice(0, 4), 1212 propertyEntry("prototype"), 1213 ...functionMembers.slice(4), 1214 ]; 1215 1216 // TODO: Shouldn't propose type keywords in statement position 1217 export const statementKeywordsWithTypes: readonly ExpectedCompletionEntryObject[] = [ 1218 "break", 1219 "case", 1220 "catch", 1221 "class", 1222 "struct", 1223 "const", 1224 "continue", 1225 "debugger", 1226 "default", 1227 "delete", 1228 "do", 1229 "else", 1230 "enum", 1231 "export", 1232 "extends", 1233 "false", 1234 "finally", 1235 "for", 1236 "function", 1237 "if", 1238 "import", 1239 "in", 1240 "instanceof", 1241 "new", 1242 "null", 1243 "return", 1244 "super", 1245 "switch", 1246 "this", 1247 "throw", 1248 "true", 1249 "try", 1250 "typeof", 1251 "var", 1252 "void", 1253 "while", 1254 "with", 1255 "implements", 1256 "interface", 1257 "let", 1258 "package", 1259 "yield", 1260 "as", 1261 "asserts", 1262 "any", 1263 "async", 1264 "await", 1265 "boolean", 1266 "declare", 1267 "infer", 1268 "keyof", 1269 "module", 1270 "namespace", 1271 "never", 1272 "readonly", 1273 "number", 1274 "object", 1275 "string", 1276 "symbol", 1277 "type", 1278 "unique", 1279 "unknown", 1280 "bigint", 1281 ].map(keywordEntry); 1282 1283 export const statementKeywords: readonly ExpectedCompletionEntryObject[] = statementKeywordsWithTypes.filter(k => { 1284 const name = k.name; 1285 switch (name) { 1286 case "false": 1287 case "true": 1288 case "null": 1289 case "void": 1290 return true; 1291 case "declare": 1292 case "module": 1293 return false; 1294 default: 1295 return !ts.contains(typeKeywords, k); 1296 } 1297 }); 1298 1299 export const statementInJsKeywords = getInJsKeywords(statementKeywords); 1300 1301 export const globalsVars: readonly ExpectedCompletionEntryObject[] = [ 1302 functionEntry("eval"), 1303 functionEntry("parseInt"), 1304 functionEntry("parseFloat"), 1305 functionEntry("isNaN"), 1306 functionEntry("isFinite"), 1307 functionEntry("decodeURI"), 1308 functionEntry("decodeURIComponent"), 1309 functionEntry("encodeURI"), 1310 functionEntry("encodeURIComponent"), 1311 functionEntry("escape"), 1312 functionEntry("unescape"), 1313 varEntry("NaN"), 1314 varEntry("Infinity"), 1315 varEntry("Object"), 1316 varEntry("Function"), 1317 varEntry("String"), 1318 varEntry("Boolean"), 1319 varEntry("Number"), 1320 varEntry("Math"), 1321 varEntry("Date"), 1322 varEntry("RegExp"), 1323 varEntry("Error"), 1324 varEntry("EvalError"), 1325 varEntry("RangeError"), 1326 varEntry("ReferenceError"), 1327 varEntry("SyntaxError"), 1328 varEntry("TypeError"), 1329 varEntry("URIError"), 1330 varEntry("JSON"), 1331 varEntry("Array"), 1332 varEntry("ArrayBuffer"), 1333 varEntry("DataView"), 1334 varEntry("Int8Array"), 1335 varEntry("Uint8Array"), 1336 varEntry("Uint8ClampedArray"), 1337 varEntry("Int16Array"), 1338 varEntry("Uint16Array"), 1339 varEntry("Int32Array"), 1340 varEntry("Uint32Array"), 1341 varEntry("Float32Array"), 1342 varEntry("Float64Array"), 1343 moduleEntry("Intl"), 1344 ]; 1345 1346 const globalKeywordsInsideFunction: readonly ExpectedCompletionEntryObject[] = [ 1347 "break", 1348 "case", 1349 "catch", 1350 "class", 1351 "struct", 1352 "const", 1353 "continue", 1354 "debugger", 1355 "default", 1356 "delete", 1357 "do", 1358 "else", 1359 "enum", 1360 "export", 1361 "extends", 1362 "false", 1363 "finally", 1364 "for", 1365 "function", 1366 "if", 1367 "import", 1368 "in", 1369 "instanceof", 1370 "new", 1371 "null", 1372 "return", 1373 "super", 1374 "switch", 1375 "this", 1376 "throw", 1377 "true", 1378 "try", 1379 "typeof", 1380 "var", 1381 "void", 1382 "while", 1383 "with", 1384 "implements", 1385 "interface", 1386 "let", 1387 "package", 1388 "yield", 1389 "as", 1390 "async", 1391 "await", 1392 ].map(keywordEntry); 1393 1394 export const undefinedVarEntry: ExpectedCompletionEntry = { 1395 name: "undefined", 1396 kind: "var", 1397 sortText: SortText.GlobalsOrKeywords 1398 }; 1399 // TODO: many of these are inappropriate to always provide 1400 export const globalsInsideFunction = (plus: readonly ExpectedCompletionEntry[]): readonly ExpectedCompletionEntry[] => [ 1401 { name: "arguments", kind: "local var" }, 1402 ...plus, 1403 globalThisEntry, 1404 ...globalsVars, 1405 undefinedVarEntry, 1406 ...globalKeywordsInsideFunction, 1407 ]; 1408 1409 const globalInJsKeywordsInsideFunction = getInJsKeywords(globalKeywordsInsideFunction); 1410 1411 // TODO: many of these are inappropriate to always provide 1412 export const globalsInJsInsideFunction = (plus: readonly ExpectedCompletionEntry[]): readonly ExpectedCompletionEntry[] => [ 1413 { name: "arguments", kind: "local var" }, 1414 globalThisEntry, 1415 ...globalsVars, 1416 ...plus, 1417 undefinedVarEntry, 1418 ...globalInJsKeywordsInsideFunction, 1419 ]; 1420 1421 // TODO: many of these are inappropriate to always provide 1422 export const globalKeywords: readonly ExpectedCompletionEntryObject[] = [ 1423 "break", 1424 "case", 1425 "catch", 1426 "class", 1427 "struct", 1428 "const", 1429 "continue", 1430 "debugger", 1431 "default", 1432 "delete", 1433 "do", 1434 "else", 1435 "enum", 1436 "export", 1437 "extends", 1438 "false", 1439 "finally", 1440 "for", 1441 "function", 1442 "if", 1443 "import", 1444 "in", 1445 "instanceof", 1446 "new", 1447 "null", 1448 "return", 1449 "super", 1450 "switch", 1451 "this", 1452 "throw", 1453 "true", 1454 "try", 1455 "typeof", 1456 "var", 1457 "void", 1458 "while", 1459 "with", 1460 "implements", 1461 "interface", 1462 "let", 1463 "package", 1464 "yield", 1465 "as", 1466 "asserts", 1467 "any", 1468 "async", 1469 "await", 1470 "boolean", 1471 "declare", 1472 "infer", 1473 "keyof", 1474 "module", 1475 "namespace", 1476 "never", 1477 "readonly", 1478 "number", 1479 "object", 1480 "string", 1481 "symbol", 1482 "type", 1483 "unique", 1484 "unknown", 1485 "bigint", 1486 ].map(keywordEntry); 1487 1488 export const globalInJsKeywords = getInJsKeywords(globalKeywords); 1489 1490 export const insideMethodKeywords: readonly ExpectedCompletionEntryObject[] = [ 1491 "break", 1492 "case", 1493 "catch", 1494 "class", 1495 "struct", 1496 "const", 1497 "continue", 1498 "debugger", 1499 "default", 1500 "delete", 1501 "do", 1502 "else", 1503 "enum", 1504 "export", 1505 "extends", 1506 "false", 1507 "finally", 1508 "for", 1509 "function", 1510 "if", 1511 "import", 1512 "in", 1513 "instanceof", 1514 "new", 1515 "null", 1516 "return", 1517 "super", 1518 "switch", 1519 "this", 1520 "throw", 1521 "true", 1522 "try", 1523 "typeof", 1524 "var", 1525 "void", 1526 "while", 1527 "with", 1528 "implements", 1529 "interface", 1530 "let", 1531 "package", 1532 "yield", 1533 "as", 1534 "async", 1535 "await", 1536 ].map(keywordEntry); 1537 1538 export const insideMethodInJsKeywords = getInJsKeywords(insideMethodKeywords); 1539 1540 export const globals: readonly ExpectedCompletionEntryObject[] = [ 1541 globalThisEntry, 1542 ...globalsVars, 1543 undefinedVarEntry, 1544 ...globalKeywords 1545 ]; 1546 1547 export const globalsInJs: readonly ExpectedCompletionEntryObject[] = [ 1548 globalThisEntry, 1549 ...globalsVars, 1550 undefinedVarEntry, 1551 ...globalInJsKeywords 1552 ]; 1553 1554 export function globalsPlus(plus: readonly ExpectedCompletionEntry[]): readonly ExpectedCompletionEntry[] { 1555 return [ 1556 globalThisEntry, 1557 ...globalsVars, 1558 ...plus, 1559 undefinedVarEntry, 1560 ...globalKeywords]; 1561 } 1562 1563 export function globalsInJsPlus(plus: readonly ExpectedCompletionEntry[]): readonly ExpectedCompletionEntry[] { 1564 return [ 1565 globalThisEntry, 1566 ...globalsVars, 1567 ...plus, 1568 undefinedVarEntry, 1569 ...globalInJsKeywords]; 1570 } 1571 } 1572 1573 export interface ReferenceGroup { 1574 definition: ReferenceGroupDefinition; 1575 ranges: FourSlash.Range[]; 1576 } 1577 1578 export type ReferenceGroupDefinition = string | { text: string, range: FourSlash.Range }; 1579 1580 export interface ApplyRefactorOptions { 1581 refactorName: string; 1582 actionName: string; 1583 actionDescription: string; 1584 newContent: NewFileContent; 1585 triggerReason?: ts.RefactorTriggerReason; 1586 } 1587 1588 export type ExpectedCompletionEntry = string | ExpectedCompletionEntryObject; 1589 export interface ExpectedCompletionEntryObject { 1590 readonly name: string; 1591 readonly source?: string; 1592 readonly insertText?: string; 1593 readonly replacementSpan?: FourSlash.Range; 1594 readonly hasAction?: boolean; // If not specified, will assert that this is false. 1595 readonly isRecommended?: boolean; // If not specified, will assert that this is false. 1596 readonly isFromUncheckedFile?: boolean; // If not specified, won't assert about this 1597 readonly kind?: string; // If not specified, won't assert about this 1598 readonly isPackageJsonImport?: boolean; // If not specified, won't assert about this 1599 readonly kindModifiers?: string; // Must be paired with 'kind' 1600 readonly text?: string; 1601 readonly documentation?: string; 1602 readonly sourceDisplay?: string; 1603 readonly tags?: readonly ts.JSDocTagInfo[]; 1604 readonly sortText?: ts.Completions.SortText; 1605 } 1606 1607 export interface VerifyCompletionsOptions { 1608 readonly marker?: ArrayOrSingle<string | FourSlash.Marker>; 1609 readonly isNewIdentifierLocation?: boolean; // Always tested 1610 readonly isGlobalCompletion?: boolean; // Only tested if set 1611 readonly optionalReplacementSpan?: FourSlash.Range; // Only tested if set 1612 readonly exact?: ArrayOrSingle<ExpectedCompletionEntry>; 1613 readonly includes?: ArrayOrSingle<ExpectedCompletionEntry>; 1614 readonly excludes?: ArrayOrSingle<string>; 1615 readonly preferences?: ts.UserPreferences; 1616 readonly triggerCharacter?: ts.CompletionsTriggerCharacter; 1617 } 1618 1619 export interface VerifySignatureHelpOptions { 1620 readonly marker?: ArrayOrSingle<string | FourSlash.Marker>; 1621 /** @default 1 */ 1622 readonly overloadsCount?: number; 1623 /** @default undefined */ 1624 readonly docComment?: string; 1625 readonly text?: string; 1626 readonly parameterName?: string; 1627 readonly parameterSpan?: string; 1628 /** @default undefined */ 1629 readonly parameterDocComment?: string; 1630 readonly parameterCount?: number; 1631 readonly argumentCount?: number; 1632 /** @default false */ 1633 readonly isVariadic?: boolean; 1634 /** @default ts.emptyArray */ 1635 readonly tags?: readonly ts.JSDocTagInfo[]; 1636 readonly triggerReason?: ts.SignatureHelpTriggerReason; 1637 readonly overrideSelectedItemIndex?: number; 1638 } 1639 1640 export interface VerifyNavigateToOptions { 1641 readonly pattern: string; 1642 readonly fileName?: string; 1643 readonly expected: readonly ExpectedNavigateToItem[]; 1644 } 1645 1646 export interface ExpectedNavigateToItem { 1647 readonly name: string; 1648 readonly kind: ts.ScriptElementKind; 1649 readonly kindModifiers?: string; 1650 readonly matchKind?: keyof typeof ts.PatternMatchKind; 1651 readonly isCaseSensitive?: boolean; 1652 readonly range: FourSlash.Range; 1653 readonly containerName?: string; 1654 readonly containerKind?: ts.ScriptElementKind; 1655 } 1656 1657 export type ArrayOrSingle<T> = T | readonly T[]; 1658 1659 export interface VerifyCompletionListContainsOptions extends ts.UserPreferences { 1660 triggerCharacter?: ts.CompletionsTriggerCharacter; 1661 sourceDisplay: string; 1662 isRecommended?: true; 1663 insertText?: string; 1664 replacementSpan?: FourSlash.Range; 1665 } 1666 1667 export interface VerifyDocumentHighlightsOptions { 1668 filesToSearch?: readonly string[]; 1669 } 1670 1671 export type NewFileContent = string | { readonly [filename: string]: string }; 1672 1673 export interface NewContentOptions { 1674 // Exactly one of these should be defined. 1675 newFileContent?: NewFileContent; 1676 newRangeContent?: string; 1677 } 1678 1679 export interface VerifyCodeFixOptions extends NewContentOptions { 1680 readonly description: string | [string, ...(string | number)[]] | DiagnosticIgnoredInterpolations; 1681 readonly errorCode?: number; 1682 readonly index?: number; 1683 readonly preferences?: ts.UserPreferences; 1684 readonly applyChanges?: boolean; 1685 readonly commands?: readonly ts.CodeActionCommand[]; 1686 } 1687 1688 export interface VerifyCodeFixAvailableOptions { 1689 description: string; 1690 commands?: ts.CodeActionCommand[]; 1691 } 1692 1693 export interface VerifyCodeFixAllOptions { 1694 fixId: string; 1695 fixAllDescription: string; 1696 newFileContent: NewFileContent; 1697 commands: readonly {}[]; 1698 } 1699 1700 export interface VerifyRefactorOptions { 1701 name: string; 1702 actionName: string; 1703 refactors: readonly ts.ApplicableRefactorInfo[]; 1704 } 1705 1706 export interface VerifyCompletionActionOptions extends NewContentOptions { 1707 name: string; 1708 source?: string; 1709 description: string; 1710 preferences?: ts.UserPreferences; 1711 } 1712 1713 export interface Diagnostic { 1714 message: string; 1715 range?: FourSlash.Range; 1716 code: number; 1717 reportsUnnecessary?: true; 1718 reportsDeprecated?: true; 1719 } 1720 1721 export interface GetEditsForFileRenameOptions { 1722 readonly oldPath: string; 1723 readonly newPath: string; 1724 readonly newFileContents: { readonly [fileName: string]: string }; 1725 readonly preferences?: ts.UserPreferences; 1726 } 1727 1728 export interface MoveToNewFileOptions { 1729 readonly newFileContents: { readonly [fileName: string]: string }; 1730 readonly preferences?: ts.UserPreferences; 1731 } 1732 1733 export type RenameLocationsOptions = readonly RenameLocationOptions[] | { 1734 readonly findInStrings?: boolean; 1735 readonly findInComments?: boolean; 1736 readonly ranges: readonly RenameLocationOptions[]; 1737 readonly providePrefixAndSuffixTextForRename?: boolean; 1738 }; 1739 export interface DiagnosticIgnoredInterpolations { 1740 template: string 1741 }; 1742 export type RenameLocationOptions = FourSlash.Range | { readonly range: FourSlash.Range, readonly prefixText?: string, readonly suffixText?: string }; 1743 export interface RenameOptions { 1744 readonly findInStrings?: boolean; 1745 readonly findInComments?: boolean; 1746 readonly providePrefixAndSuffixTextForRename?: boolean; 1747 }; 1748} 1749