Merge pull request #15545 from aozgaa/atTypesPrefixAndImportSuffix

At types prefix and import suffix
This commit is contained in:
Arthur Ozga
2017-05-22 16:53:04 -07:00
committed by GitHub
6 changed files with 51 additions and 13 deletions

View File

@@ -1783,7 +1783,8 @@ namespace ts {
return path.length > extension.length && endsWith(path, extension);
}
export function fileExtensionIsAny(path: string, extensions: string[]): boolean {
/* @internal */
export function fileExtensionIsOneOf(path: string, extensions: string[]): boolean {
for (const extension of extensions) {
if (fileExtensionIs(path, extension)) {
return true;
@@ -1983,7 +1984,7 @@ namespace ts {
for (const current of files) {
const name = combinePaths(path, current);
const absoluteName = combinePaths(absolutePath, current);
if (extensions && !fileExtensionIsAny(name, extensions)) continue;
if (extensions && !fileExtensionIsOneOf(name, extensions)) continue;
if (excludeRegex && excludeRegex.test(absoluteName)) continue;
if (!includeFileRegexes) {
results[0].push(name);

View File

@@ -971,10 +971,13 @@ namespace ts {
}
}
/** Double underscores are used in DefinitelyTyped to delimit scoped packages. */
const mangledScopedPackageSeparator = "__";
/** For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. */
function mangleScopedPackage(moduleName: string, state: ModuleResolutionState): string {
if (startsWith(moduleName, "@")) {
const replaceSlash = moduleName.replace(ts.directorySeparator, "__");
const replaceSlash = moduleName.replace(ts.directorySeparator, mangledScopedPackageSeparator);
if (replaceSlash !== moduleName) {
const mangled = replaceSlash.slice(1); // Take off the "@"
if (state.traceEnabled) {
@@ -986,6 +989,17 @@ namespace ts {
return moduleName;
}
/* @internal */
export function getPackageNameFromAtTypesDirectory(mangledName: string): string {
const withoutAtTypePrefix = removePrefix(mangledName, "@types/");
if (withoutAtTypePrefix !== mangledName) {
return withoutAtTypePrefix.indexOf("__") !== -1 ?
"@" + withoutAtTypePrefix.replace(mangledScopedPackageSeparator, ts.directorySeparator) :
withoutAtTypePrefix;
}
return mangledName;
}
function tryFindNonRelativeModuleNameInCache(cache: PerModuleNameCache | undefined, moduleName: string, containingDirectory: string, traceEnabled: boolean, host: ModuleResolutionHost): SearchResult<Resolved> {
const result = cache && cache.get(containingDirectory);
if (result) {

View File

@@ -523,7 +523,7 @@ namespace ts.codefix {
catch (e) { }
}
return relativeFileName;
return getPackageNameFromAtTypesDirectory(relativeFileName);
}
}

View File

@@ -245,18 +245,15 @@ namespace ts.Completions.PathCompletions {
// Get modules that the type checker picked up
const ambientModules = map(typeChecker.getAmbientModules(), sym => stripQuotes(sym.name));
let nonRelativeModules = filter(ambientModules, moduleName => startsWith(moduleName, fragment));
let nonRelativeModuleNames = filter(ambientModules, moduleName => startsWith(moduleName, fragment));
// Nested modules of the form "module-name/sub" need to be adjusted to only return the string
// after the last '/' that appears in the fragment because that's where the replacement span
// starts
if (isNestedModule) {
const moduleNameWithSeperator = ensureTrailingDirectorySeparator(moduleNameFragment);
nonRelativeModules = map(nonRelativeModules, moduleName => {
if (startsWith(fragment, moduleNameWithSeperator)) {
return moduleName.substr(moduleNameWithSeperator.length);
}
return moduleName;
nonRelativeModuleNames = map(nonRelativeModuleNames, nonRelativeModuleName => {
return removePrefix(nonRelativeModuleName, moduleNameWithSeperator);
});
}
@@ -264,7 +261,7 @@ namespace ts.Completions.PathCompletions {
if (!options.moduleResolution || options.moduleResolution === ModuleResolutionKind.NodeJs) {
for (const visibleModule of enumerateNodeModulesVisibleToScript(host, scriptPath)) {
if (!isNestedModule) {
nonRelativeModules.push(visibleModule.moduleName);
nonRelativeModuleNames.push(visibleModule.moduleName);
}
else if (startsWith(visibleModule.moduleName, moduleNameFragment)) {
const nestedFiles = tryReadDirectory(host, visibleModule.moduleDir, supportedTypeScriptExtensions, /*exclude*/ undefined, /*include*/ ["./*"]);
@@ -272,14 +269,14 @@ namespace ts.Completions.PathCompletions {
for (let f of nestedFiles) {
f = normalizePath(f);
const nestedModule = removeFileExtension(getBaseFileName(f));
nonRelativeModules.push(nestedModule);
nonRelativeModuleNames.push(nestedModule);
}
}
}
}
}
return deduplicate(nonRelativeModules);
return deduplicate(nonRelativeModuleNames);
}
export function getTripleSlashReferenceCompletion(sourceFile: SourceFile, position: number, compilerOptions: CompilerOptions, host: LanguageServiceHost): CompletionInfo {

View File

@@ -0,0 +1,13 @@
/// <reference path="fourslash.ts" />
//// [|f1/*0*/();|]
// @Filename: node_modules/@types/myLib/index.d.ts
//// export function f1() {}
//// export var v1 = 5;
verify.importFixAtPosition([
`import { f1 } from "myLib";
f1();`
]);

View File

@@ -0,0 +1,13 @@
/// <reference path="fourslash.ts" />
//// [|f1/*0*/();|]
// @Filename: node_modules/@types/myLib__scoped/index.d.ts
//// export function f1() {}
//// export var v1 = 5;
verify.importFixAtPosition([
`import { f1 } from "@myLib/scoped";
f1();`
]);