mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-15 11:35:42 -06:00
Replacement spans for import completions
This commit is contained in:
parent
4ec8b2b134
commit
98a162be2a
@ -766,13 +766,29 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public verifyImportModuleCompletionListContains(symbol: string) {
|
||||
public verifyImportModuleCompletionListContains(symbol: string, rangeIndex?: number) {
|
||||
const completions = this.getImportModuleCompletionListAtCaret();
|
||||
if (completions) {
|
||||
if (!ts.forEach(completions, completion => completion.name === symbol)) {
|
||||
const completion = ts.forEach(completions, completion => completion.name === symbol ? completion : undefined);
|
||||
if (!completion) {
|
||||
const itemsString = completions.map(item => stringify({ name: item.name, span: item.span })).join(",\n");
|
||||
this.raiseError(`Expected "${symbol}" to be in list [${itemsString}]`);
|
||||
}
|
||||
else if (rangeIndex !== undefined) {
|
||||
const ranges = this.getRanges();
|
||||
if (ranges && ranges.length > rangeIndex) {
|
||||
const range = ranges[rangeIndex];
|
||||
|
||||
const start = completion.span.start;
|
||||
const end = start + completion.span.length;
|
||||
if (range.start !== start || range.end !== end) {
|
||||
this.raiseError(`Expected completion span for '${symbol}', ${stringify(completion.span)}, to cover range ${stringify(range)}`);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.raiseError(`Expected completion span for '${symbol}' to cover range at index ${rangeIndex}, but no range was found at that index`);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.raiseError(`No import module completions at position '${this.currentCaretPosition}' when looking for '${symbol}'.`);
|
||||
@ -2943,12 +2959,12 @@ namespace FourSlashInterface {
|
||||
this.state.verifyCompletionListItemsCountIsGreaterThan(count, this.negative);
|
||||
}
|
||||
|
||||
public importModuleCompletionListContains(symbol: string): void {
|
||||
public importModuleCompletionListContains(symbol: string, rangeIndex?: number): void {
|
||||
if (this.negative) {
|
||||
this.state.verifyImportModuleCompletionListDoesNotContain(symbol);
|
||||
}
|
||||
else {
|
||||
this.state.verifyImportModuleCompletionListContains(symbol);
|
||||
this.state.verifyImportModuleCompletionListContains(symbol, rangeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -2069,7 +2069,7 @@ namespace ts {
|
||||
* for completions.
|
||||
* For example, this matches /// <reference path="fragment
|
||||
*/
|
||||
const tripleSlashDirectiveFragmentRegex = /^\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|")([^'"]+)$/;
|
||||
const tripleSlashDirectiveFragmentRegex = /^(\/\/\/\s*<reference\s+(path|types)\s*=\s*(?:'|"))([^'"]+)$/;
|
||||
|
||||
let commandLineOptionsStringToEnum: CommandLineOptionOfCustomType[];
|
||||
|
||||
@ -4517,8 +4517,8 @@ namespace ts {
|
||||
const literalValue = node.text;
|
||||
let result: ImportCompletionEntry[];
|
||||
|
||||
const nodeStart = node.getStart();
|
||||
const span: TextSpan = { start: nodeStart, length: nodeStart - node.getEnd() };
|
||||
// Replace the entire text of the string literal (excluding the quotes)
|
||||
const span: TextSpan = { start: node.getStart() + 1, length: literalValue.length };
|
||||
|
||||
const isRelativePath = startsWith(literalValue, ".");
|
||||
const scriptDir = getDirectoryPath(node.getSourceFile().path);
|
||||
@ -4768,22 +4768,36 @@ namespace ts {
|
||||
}
|
||||
|
||||
function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number): ImportCompletionEntry[] {
|
||||
const node = getTokenAtPosition(sourceFile, position);
|
||||
if (!node) {
|
||||
const token = getTokenAtPosition(sourceFile, position);
|
||||
if (!token) {
|
||||
return undefined;
|
||||
}
|
||||
const commentRanges: CommentRange[] = getLeadingCommentRanges(sourceFile.text, token.pos);
|
||||
|
||||
if (!commentRanges || !commentRanges.length) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const span: TextSpan = undefined;
|
||||
const range = forEach(commentRanges, commentRange => position >= commentRange.pos && position <= commentRange.end && commentRange);
|
||||
|
||||
if (!range) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const text = sourceFile.text.substr(range.pos, position - range.pos);
|
||||
|
||||
const text = sourceFile.text.substr(node.pos, position);
|
||||
const match = tripleSlashDirectiveFragmentRegex.exec(text);
|
||||
if (match) {
|
||||
const kind= match[1];
|
||||
const fragment = match[2];
|
||||
const prefix = match[1];
|
||||
const kind = match[2];
|
||||
const toComplete = match[3];
|
||||
|
||||
const span: TextSpan = { start: range.pos + prefix.length, length: match[0].length - prefix.length };
|
||||
|
||||
const scriptPath = getDirectoryPath(sourceFile.path);
|
||||
if (kind === "path") {
|
||||
// Give completions for a relative path
|
||||
return getCompletionEntriesForDirectoryFragment(fragment, scriptPath, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/true, span);
|
||||
return getCompletionEntriesForDirectoryFragment(toComplete, scriptPath, getSupportedExtensions(program.getCompilerOptions()), /*includeExtensions*/true, span);
|
||||
}
|
||||
else {
|
||||
// Give completions based on the typings available
|
||||
|
||||
19
tests/cases/fourslash/completionForStringLiteralImport1.ts
Normal file
19
tests/cases/fourslash/completionForStringLiteralImport1.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: test.ts
|
||||
//// import * as foo0 from "[|./some|]/*0*/
|
||||
//// import foo1 = require( "[|./some|]/*1*/
|
||||
//// var foo2 = require( "[|./some|]/*2*/
|
||||
|
||||
//// import * as foo3 from "[|./some|]/*3*/";
|
||||
//// import foo4 = require( "[|./some|]/*4*/";
|
||||
//// var foo5 = require( "[|./some|]/*5*/";
|
||||
|
||||
|
||||
// @Filename: someFile.ts
|
||||
//// /*someFile*/
|
||||
|
||||
for (let i = 0; i < 6; i++) {
|
||||
goTo.marker("" + i);
|
||||
verify.importModuleCompletionListContains("someFile", i);
|
||||
}
|
||||
28
tests/cases/fourslash/completionForStringLiteralImport2.ts
Normal file
28
tests/cases/fourslash/completionForStringLiteralImport2.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @typeRoots: my_typings
|
||||
|
||||
// @Filename: test.ts
|
||||
//// /// <reference path="[|./some|]/*0*/
|
||||
//// /// <reference types="[|some|]/*1*/
|
||||
|
||||
//// /// <reference path="[|./some|]/*2*/" />
|
||||
//// /// <reference types="[|some|]/*3*/" />
|
||||
|
||||
// @Filename: someFile.ts
|
||||
//// /*someFile*/
|
||||
|
||||
// @Filename: my_typings/some-module/index.d.ts
|
||||
//// export var x = 9;
|
||||
|
||||
goTo.marker("0");
|
||||
verify.importModuleCompletionListContains("someFile.ts", 0);
|
||||
|
||||
goTo.marker("1");
|
||||
verify.importModuleCompletionListContains("some-module", 1);
|
||||
|
||||
goTo.marker("2");
|
||||
verify.importModuleCompletionListContains("someFile.ts", 2);
|
||||
|
||||
goTo.marker("3");
|
||||
verify.importModuleCompletionListContains("some-module", 3);
|
||||
@ -125,7 +125,7 @@ declare namespace FourSlashInterface {
|
||||
completionListItemsCountIsGreaterThan(count: number): void;
|
||||
completionListIsEmpty(): void;
|
||||
completionListAllowsNewIdentifier(): void;
|
||||
importModuleCompletionListContains(symbol: string): void;
|
||||
importModuleCompletionListContains(symbol: string, rangeIndex?: number): void;
|
||||
importModuleCompletionListItemsCountIsGreaterThan(count: number): void;
|
||||
importModuleCompletionListIsEmpty(): void;
|
||||
memberListIsEmpty(): void;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user