From 86210b38c5662ae8a66584e52cc0794c9c4412a3 Mon Sep 17 00:00:00 2001 From: Andy Date: Tue, 6 Feb 2018 11:39:09 -0800 Subject: [PATCH] Remove leading directory separator from path mapping completion (#21688) --- src/services/pathCompletions.ts | 19 +++++++++++-------- .../fourslash/completionsPaths_pathMapping.ts | 8 +++++--- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 10899da37ecdf..32b7f94c88b6b 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -179,7 +179,7 @@ namespace ts.Completions.PathCompletions { function getCompletionsForPathMapping( path: string, patterns: ReadonlyArray, fragment: string, baseUrl: string, fileExtensions: ReadonlyArray, host: LanguageServiceHost, - ): string[] { + ): ReadonlyArray { if (!endsWith(path, "*")) { // For a path mapping "foo": ["/x/y/z.ts"], add "foo" itself as a completion. return !stringContains(path, "*") && startsWith(path, fragment) ? [path] : emptyArray; @@ -231,16 +231,19 @@ namespace ts.Completions.PathCompletions { // Trim away prefix and suffix return mapDefined(concatenate(matches, directories), match => { const normalizedMatch = normalizePath(match); - if (!endsWith(normalizedMatch, normalizedSuffix) || !startsWith(normalizedMatch, completePrefix)) { - return; - } - - const start = completePrefix.length; - const length = normalizedMatch.length - start - normalizedSuffix.length; - return removeFileExtension(normalizedMatch.substr(start, length)); + const inner = withoutStartAndEnd(normalizedMatch, completePrefix, normalizedSuffix); + return inner !== undefined ? removeLeadingDirectorySeparator(removeFileExtension(inner)) : undefined; }); } + function withoutStartAndEnd(s: string, start: string, end: string): string | undefined { + return startsWith(s, start) && endsWith(s, end) ? s.slice(start.length, s.length - end.length) : undefined; + } + + function removeLeadingDirectorySeparator(path: string): string { + return path[0] === directorySeparator ? path.slice(1) : path; + } + function enumeratePotentialNonRelativeModules(fragment: string, scriptPath: string, options: CompilerOptions, typeChecker: TypeChecker, host: LanguageServiceHost): string[] { // Check If this is a nested module const isNestedModule = stringContains(fragment, directorySeparator); diff --git a/tests/cases/fourslash/completionsPaths_pathMapping.ts b/tests/cases/fourslash/completionsPaths_pathMapping.ts index 80e0fa26d9fc9..1c222545ae696 100644 --- a/tests/cases/fourslash/completionsPaths_pathMapping.ts +++ b/tests/cases/fourslash/completionsPaths_pathMapping.ts @@ -7,7 +7,8 @@ /////export const x = 0; // @Filename: /src/a.ts -////import {} from "foo/[|/**/|]"; +////import {} from "foo/[|/*0*/|]"; +////import {} from "foo/dir/[|/*1*/|]"; // @Filename: /tsconfig.json ////{ @@ -19,5 +20,6 @@ //// } ////} -const [replacementSpan] = test.ranges(); -verify.completionsAt("", ["a", "b", "dir"].map(name => ({ name, replacementSpan }))); +const [r0, r1] = test.ranges(); +verify.completionsAt("0", ["a", "b", "dir"].map(name => ({ name, replacementSpan: r0 }))); +verify.completionsAt("1", ["x"].map(name => ({ name, replacementSpan: r1 })));