diff --git a/src/compiler/path.ts b/src/compiler/path.ts index d7df5eefb2f4f..d4ee8600d7190 100644 --- a/src/compiler/path.ts +++ b/src/compiler/path.ts @@ -6,7 +6,7 @@ namespace ts { * we expect the host to correctly handle paths in our specified format. */ export const directorySeparator = "/"; - const altDirectorySeparator = "\\"; + export const altDirectorySeparator = "\\"; const urlSchemeSeparator = "://"; const backslashRegExp = /\\/g; diff --git a/src/services/stringCompletions.ts b/src/services/stringCompletions.ts index c9d57642ec194..a355a791695b0 100644 --- a/src/services/stringCompletions.ts +++ b/src/services/stringCompletions.ts @@ -279,7 +279,9 @@ namespace ts.Completions.StringCompletions { function addReplacementSpans(text: string, textStart: number, names: readonly NameAndKind[]): readonly PathCompletion[] { const span = getDirectoryFragmentTextSpan(text, textStart); - return names.map(({ name, kind, extension }): PathCompletion => ({ name, kind, extension, span })); + const wholeSpan = text.length === 0 ? undefined : createTextSpan(textStart, text.length); + return names.map(({ name, kind, extension }): PathCompletion => + Math.max(name.indexOf(directorySeparator), name.indexOf(altDirectorySeparator)) !== -1 ? { name, kind, extension, span: wholeSpan } : { name, kind, extension, span }); } function getStringLiteralCompletionsFromModuleNames(sourceFile: SourceFile, node: LiteralExpression, compilerOptions: CompilerOptions, host: LanguageServiceHost, typeChecker: TypeChecker): readonly PathCompletion[] { @@ -683,7 +685,7 @@ namespace ts.Completions.StringCompletions { // Replace everything after the last directory separator that appears function getDirectoryFragmentTextSpan(text: string, textStart: number): TextSpan | undefined { - const index = Math.max(text.lastIndexOf(directorySeparator), text.lastIndexOf("\\")); + const index = Math.max(text.lastIndexOf(directorySeparator), text.lastIndexOf(altDirectorySeparator)); const offset = index !== -1 ? index + 1 : 0; // If the range is an identifier, span is unnecessary. const length = text.length - offset; diff --git a/tests/cases/fourslash/completionForStringLiteralNonrelativeImport14.ts b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport14.ts index dac27a6c30785..2f683082db2da 100644 --- a/tests/cases/fourslash/completionForStringLiteralNonrelativeImport14.ts +++ b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport14.ts @@ -25,4 +25,69 @@ // @Filename: some/other/path.ts //// export var y = 10; -verify.completions({ marker: test.markerNames(), exact: ["lib", "tests", "/module1", "/module2"], isNewIdentifierLocation: true }); +verify.completions({ + marker: ["import_as0",], + exact: ["lib", "tests", + { + name: "/module1", + replacementSpan: { + fileName: "foo", + pos: 23, + end: 24 + } + }, + { + name: "/module2", + replacementSpan: { + fileName: "foo", + pos: 23, + end: 24 + } + }], + isNewIdentifierLocation: true +}); + + +verify.completions({ + marker: ["import_equals0",], + exact: ["lib", "tests", + { + name: "/module1", + replacementSpan: { + fileName: "foo", + pos: 48, + end: 49 + } + }, + { + name: "/module2", + replacementSpan: { + fileName: "foo", + pos: 48, + end: 49 + } + }], + isNewIdentifierLocation: true +}); + +verify.completions({ + marker: ["require0",], + exact: ["lib", "tests", + { + name: "/module1", + replacementSpan: { + fileName: "foo", + pos: 70, + end: 71 + } + }, + { + name: "/module2", + replacementSpan: { + fileName: "foo", + pos: 70, + end: 71 + } + }], + isNewIdentifierLocation: true +}); diff --git a/tests/cases/fourslash/completionForStringLiteralNonrelativeImport16.ts b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport16.ts new file mode 100644 index 0000000000000..f5c1cf282c469 --- /dev/null +++ b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport16.ts @@ -0,0 +1,40 @@ +/// + +// Should give completions for modules referenced via baseUrl and paths compiler options with explicit name mappings + +// @Filename: tsconfig.json +//// { +//// "compilerOptions": { +//// "baseUrl": "./", +//// "paths": { +//// "module1/path1": ["some/path/whatever.ts"], +//// } +//// } +//// } + +// @Filename: test0.ts +//// import * as foo1 from "m/*first*/ +//// import * as foo1 from "module1/pa/*second*/ + +// @Filename: some/path/whatever.ts +//// export var x = 9; + +verify.completions({ marker: ["first"], exact: ["test0", "some", { + name: "module1/path1", + replacementSpan: { + fileName: "foo", + pos: 23, + end: 24 + } +}], isNewIdentifierLocation: true }); + +verify.completions({ + marker: ["second"], exact: [{ + name: "module1/path1", + replacementSpan: { + fileName: "foo", + pos: 48, + end: 58 + } + }], isNewIdentifierLocation: true +}); \ No newline at end of file