mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 02:33:53 -06:00
Eagerly resolve module specifiers for auto-import completions in --moduleResolution node12+ (#48752)
* Add failing test * Block auto-import module specifiers including node_modules path * Eagerly resolve module specifiers in completions in nodenext so failures can be filtered * Add completion info flags for telemetry * Update API baseline * Update completions baselines * Fix missed boolean flip * Fix remaining tests
This commit is contained in:
parent
717a1be3c9
commit
476fc625df
@ -8470,7 +8470,7 @@ namespace ts {
|
||||
export interface ResolvedModuleSpecifierInfo {
|
||||
modulePaths: readonly ModulePath[] | undefined;
|
||||
moduleSpecifiers: readonly string[] | undefined;
|
||||
isAutoImportable: boolean | undefined;
|
||||
isBlockedByPackageJsonDependencies: boolean | undefined;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
@ -8482,7 +8482,7 @@ namespace ts {
|
||||
export interface ModuleSpecifierCache {
|
||||
get(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions): Readonly<ResolvedModuleSpecifierInfo> | undefined;
|
||||
set(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, modulePaths: readonly ModulePath[], moduleSpecifiers: readonly string[]): void;
|
||||
setIsAutoImportable(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, isAutoImportable: boolean): void;
|
||||
setBlockedByPackageJsonDependencies(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, isBlockedByPackageJsonDependencies: boolean): void;
|
||||
setModulePaths(fromFileName: Path, toFileName: Path, preferences: UserPreferences, options: ModuleSpecifierOptions, modulePaths: readonly ModulePath[]): void;
|
||||
clear(): void;
|
||||
count(): number;
|
||||
|
||||
@ -14,7 +14,7 @@ namespace ts.server {
|
||||
return cache.get(toFileName);
|
||||
},
|
||||
set(fromFileName, toFileName, preferences, options, modulePaths, moduleSpecifiers) {
|
||||
ensureCache(fromFileName, preferences, options).set(toFileName, createInfo(modulePaths, moduleSpecifiers, /*isAutoImportable*/ true));
|
||||
ensureCache(fromFileName, preferences, options).set(toFileName, createInfo(modulePaths, moduleSpecifiers, /*isBlockedByPackageJsonDependencies*/ false));
|
||||
|
||||
// If any module specifiers were generated based off paths in node_modules,
|
||||
// a package.json file in that package was read and is an input to the cached.
|
||||
@ -43,17 +43,17 @@ namespace ts.server {
|
||||
info.modulePaths = modulePaths;
|
||||
}
|
||||
else {
|
||||
cache.set(toFileName, createInfo(modulePaths, /*moduleSpecifiers*/ undefined, /*isAutoImportable*/ undefined));
|
||||
cache.set(toFileName, createInfo(modulePaths, /*moduleSpecifiers*/ undefined, /*isBlockedByPackageJsonDependencies*/ undefined));
|
||||
}
|
||||
},
|
||||
setIsAutoImportable(fromFileName, toFileName, preferences, options, isAutoImportable) {
|
||||
setBlockedByPackageJsonDependencies(fromFileName, toFileName, preferences, options, isBlockedByPackageJsonDependencies) {
|
||||
const cache = ensureCache(fromFileName, preferences, options);
|
||||
const info = cache.get(toFileName);
|
||||
if (info) {
|
||||
info.isAutoImportable = isAutoImportable;
|
||||
info.isBlockedByPackageJsonDependencies = isBlockedByPackageJsonDependencies;
|
||||
}
|
||||
else {
|
||||
cache.set(toFileName, createInfo(/*modulePaths*/ undefined, /*moduleSpecifiers*/ undefined, isAutoImportable));
|
||||
cache.set(toFileName, createInfo(/*modulePaths*/ undefined, /*moduleSpecifiers*/ undefined, isBlockedByPackageJsonDependencies));
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
@ -87,9 +87,9 @@ namespace ts.server {
|
||||
function createInfo(
|
||||
modulePaths: readonly ModulePath[] | undefined,
|
||||
moduleSpecifiers: readonly string[] | undefined,
|
||||
isAutoImportable: boolean | undefined,
|
||||
isBlockedByPackageJsonDependencies: boolean | undefined,
|
||||
): ResolvedModuleSpecifierInfo {
|
||||
return { modulePaths, moduleSpecifiers, isAutoImportable };
|
||||
return { modulePaths, moduleSpecifiers, isBlockedByPackageJsonDependencies };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2403,6 +2403,7 @@ namespace ts.server.protocol {
|
||||
}
|
||||
|
||||
export interface CompletionInfo {
|
||||
readonly flags?: number;
|
||||
readonly isGlobalCompletion: boolean;
|
||||
readonly isMemberCompletion: boolean;
|
||||
readonly isNewIdentifierLocation: boolean;
|
||||
|
||||
@ -644,6 +644,7 @@ namespace ts.codefix {
|
||||
const compilerOptions = program.getCompilerOptions();
|
||||
const moduleSpecifierResolutionHost = createModuleSpecifierResolutionHost(program, host);
|
||||
const getChecker = memoizeOne((isFromPackageJson: boolean) => isFromPackageJson ? host.getPackageJsonAutoImportProvider!()!.getTypeChecker() : program.getTypeChecker());
|
||||
const rejectNodeModulesRelativePaths = moduleResolutionUsesNodeModules(getEmitModuleResolutionKind(compilerOptions));
|
||||
const getModuleSpecifiers = fromCacheOnly
|
||||
? (moduleSymbol: Symbol) => ({ moduleSpecifiers: moduleSpecifiers.tryGetModuleSpecifiersFromCache(moduleSymbol, sourceFile, moduleSpecifierResolutionHost, preferences), computedWithoutCache: false })
|
||||
: (moduleSymbol: Symbol, checker: TypeChecker) => moduleSpecifiers.getModuleSpecifiersWithCacheInfo(moduleSymbol, checker, compilerOptions, sourceFile, moduleSpecifierResolutionHost, preferences);
|
||||
@ -655,19 +656,19 @@ namespace ts.codefix {
|
||||
const importedSymbolHasValueMeaning = !!(exportInfo.targetFlags & SymbolFlags.Value);
|
||||
const addAsTypeOnly = getAddAsTypeOnly(isValidTypeOnlyUseSite, /*isForNewImportDeclaration*/ true, exportInfo.symbol, exportInfo.targetFlags, checker, compilerOptions);
|
||||
computedWithoutCacheCount += computedWithoutCache ? 1 : 0;
|
||||
return moduleSpecifiers?.map((moduleSpecifier): FixAddNewImport | FixAddJsdocTypeImport =>
|
||||
return mapDefined(moduleSpecifiers, (moduleSpecifier): FixAddNewImport | FixAddJsdocTypeImport | undefined =>
|
||||
rejectNodeModulesRelativePaths && pathContainsNodeModules(moduleSpecifier) ? undefined :
|
||||
// `position` should only be undefined at a missing jsx namespace, in which case we shouldn't be looking for pure types.
|
||||
!importedSymbolHasValueMeaning && isJs && position !== undefined
|
||||
? { kind: ImportFixKind.JsdocTypeImport, moduleSpecifier, position, exportInfo, isReExport: i > 0 }
|
||||
: {
|
||||
kind: ImportFixKind.AddNew,
|
||||
moduleSpecifier,
|
||||
importKind: getImportKind(sourceFile, exportInfo.exportKind, compilerOptions),
|
||||
useRequire,
|
||||
addAsTypeOnly,
|
||||
exportInfo,
|
||||
isReExport: i > 0,
|
||||
}
|
||||
!importedSymbolHasValueMeaning && isJs && position !== undefined ? { kind: ImportFixKind.JsdocTypeImport, moduleSpecifier, position, exportInfo, isReExport: i > 0 } :
|
||||
{
|
||||
kind: ImportFixKind.AddNew,
|
||||
moduleSpecifier,
|
||||
importKind: getImportKind(sourceFile, exportInfo.exportKind, compilerOptions),
|
||||
useRequire,
|
||||
addAsTypeOnly,
|
||||
exportInfo,
|
||||
isReExport: i > 0,
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@ -170,14 +170,16 @@ namespace ts.Completions {
|
||||
const enum GlobalsSearch { Continue, Success, Fail }
|
||||
|
||||
interface ModuleSpecifierResolutioContext {
|
||||
tryResolve: (exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean) => ModuleSpecifierResolutionResult | undefined;
|
||||
resolutionLimitExceeded: () => boolean;
|
||||
tryResolve: (exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean) => ModuleSpecifierResolutionResult;
|
||||
resolvedAny: () => boolean;
|
||||
skippedAny: () => boolean;
|
||||
resolvedBeyondLimit: () => boolean;
|
||||
}
|
||||
|
||||
interface ModuleSpecifierResolutionResult {
|
||||
type ModuleSpecifierResolutionResult = "skipped" | "failed" | {
|
||||
exportInfo?: SymbolExportInfo;
|
||||
moduleSpecifier: string;
|
||||
}
|
||||
};
|
||||
|
||||
function resolvingModuleSpecifiers<TReturn>(
|
||||
logPrefix: string,
|
||||
@ -192,45 +194,56 @@ namespace ts.Completions {
|
||||
): TReturn {
|
||||
const start = timestamp();
|
||||
const packageJsonImportFilter = createPackageJsonImportFilter(sourceFile, preferences, host);
|
||||
let resolutionLimitExceeded = false;
|
||||
// Under `--moduleResolution nodenext`, we have to resolve module specifiers up front, because
|
||||
// package.json exports can mean we *can't* resolve a module specifier (that doesn't include a
|
||||
// relative path into node_modules), and we want to filter those completions out entirely.
|
||||
// Import statement completions always need specifier resolution because the module specifier is
|
||||
// part of their `insertText`, not the `codeActions` creating edits away from the cursor.
|
||||
const needsFullResolution = isForImportStatementCompletion || moduleResolutionRespectsExports(getEmitModuleResolutionKind(program.getCompilerOptions()));
|
||||
let skippedAny = false;
|
||||
let ambientCount = 0;
|
||||
let resolvedCount = 0;
|
||||
let resolvedFromCacheCount = 0;
|
||||
let cacheAttemptCount = 0;
|
||||
|
||||
const result = cb({ tryResolve, resolutionLimitExceeded: () => resolutionLimitExceeded });
|
||||
const result = cb({
|
||||
tryResolve,
|
||||
skippedAny: () => skippedAny,
|
||||
resolvedAny: () => resolvedCount > 0,
|
||||
resolvedBeyondLimit: () => resolvedCount > moduleSpecifierResolutionLimit,
|
||||
});
|
||||
|
||||
const hitRateMessage = cacheAttemptCount ? ` (${(resolvedFromCacheCount / cacheAttemptCount * 100).toFixed(1)}% hit rate)` : "";
|
||||
host.log?.(`${logPrefix}: resolved ${resolvedCount} module specifiers, plus ${ambientCount} ambient and ${resolvedFromCacheCount} from cache${hitRateMessage}`);
|
||||
host.log?.(`${logPrefix}: response is ${resolutionLimitExceeded ? "incomplete" : "complete"}`);
|
||||
host.log?.(`${logPrefix}: response is ${skippedAny ? "incomplete" : "complete"}`);
|
||||
host.log?.(`${logPrefix}: ${timestamp() - start}`);
|
||||
return result;
|
||||
|
||||
function tryResolve(exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean): ModuleSpecifierResolutionResult | undefined {
|
||||
function tryResolve(exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean): ModuleSpecifierResolutionResult {
|
||||
if (isFromAmbientModule) {
|
||||
const result = codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences);
|
||||
if (result) {
|
||||
ambientCount++;
|
||||
}
|
||||
return result;
|
||||
return result || "failed";
|
||||
}
|
||||
const shouldResolveModuleSpecifier = isForImportStatementCompletion || preferences.allowIncompleteCompletions && resolvedCount < moduleSpecifierResolutionLimit;
|
||||
const shouldResolveModuleSpecifier = needsFullResolution || preferences.allowIncompleteCompletions && resolvedCount < moduleSpecifierResolutionLimit;
|
||||
const shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier && preferences.allowIncompleteCompletions && cacheAttemptCount < moduleSpecifierResolutionCacheAttemptLimit;
|
||||
const result = (shouldResolveModuleSpecifier || shouldGetModuleSpecifierFromCache)
|
||||
? codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences, packageJsonImportFilter, shouldGetModuleSpecifierFromCache)
|
||||
: undefined;
|
||||
|
||||
if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) {
|
||||
resolutionLimitExceeded = true;
|
||||
skippedAny = true;
|
||||
}
|
||||
|
||||
resolvedCount += result?.computedWithoutCacheCount || 0;
|
||||
resolvedFromCacheCount += exportInfo.length - resolvedCount;
|
||||
resolvedFromCacheCount += exportInfo.length - (result?.computedWithoutCacheCount || 0);
|
||||
if (shouldGetModuleSpecifierFromCache) {
|
||||
cacheAttemptCount++;
|
||||
}
|
||||
|
||||
return result;
|
||||
return result || (needsFullResolution ? "failed" : "skipped");
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,7 +392,11 @@ namespace ts.Completions {
|
||||
const info = exportMap.get(file.path, entry.data.exportMapKey);
|
||||
|
||||
const result = info && context.tryResolve(info, entry.name, !isExternalModuleNameRelative(stripQuotes(origin.moduleSymbol.name)));
|
||||
if (!result) return entry;
|
||||
if (result === "skipped") return entry;
|
||||
if (!result || result === "failed") {
|
||||
host.log?.(`Unexpected failure resolving auto import for '${entry.name}' from '${entry.source}'`);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const newOrigin: SymbolOriginInfoResolvedExport = {
|
||||
...origin,
|
||||
@ -394,7 +411,7 @@ namespace ts.Completions {
|
||||
return entry;
|
||||
});
|
||||
|
||||
if (!context.resolutionLimitExceeded()) {
|
||||
if (!context.skippedAny()) {
|
||||
previousResponse.isIncomplete = undefined;
|
||||
}
|
||||
|
||||
@ -403,6 +420,7 @@ namespace ts.Completions {
|
||||
);
|
||||
|
||||
previousResponse.entries = newEntries;
|
||||
previousResponse.flags = (previousResponse.flags || 0) | CompletionInfoFlags.IsContinuation;
|
||||
return previousResponse;
|
||||
}
|
||||
|
||||
@ -574,12 +592,13 @@ namespace ts.Completions {
|
||||
}
|
||||
|
||||
return {
|
||||
flags: completionData.flags,
|
||||
isGlobalCompletion: isInSnippetScope,
|
||||
isIncomplete: preferences.allowIncompleteCompletions && hasUnresolvedAutoImports ? true : undefined,
|
||||
isMemberCompletion: isMemberCompletionKind(completionKind),
|
||||
isNewIdentifierLocation,
|
||||
optionalReplacementSpan: getOptionalReplacementSpan(location),
|
||||
entries
|
||||
entries,
|
||||
};
|
||||
}
|
||||
|
||||
@ -1841,6 +1860,7 @@ namespace ts.Completions {
|
||||
readonly isRightOfOpenTag: boolean;
|
||||
readonly importCompletionNode?: Node;
|
||||
readonly hasUnresolvedAutoImports?: boolean;
|
||||
readonly flags: CompletionInfoFlags;
|
||||
}
|
||||
type Request =
|
||||
| { readonly kind: CompletionDataKind.JsDocTagName | CompletionDataKind.JsDocTag }
|
||||
@ -2025,6 +2045,7 @@ namespace ts.Completions {
|
||||
let location = getTouchingPropertyName(sourceFile, position);
|
||||
let keywordFilters = KeywordCompletionFilters.None;
|
||||
let isNewIdentifierLocation = false;
|
||||
let flags = CompletionInfoFlags.None;
|
||||
|
||||
if (contextToken) {
|
||||
const importStatementCompletion = getImportStatementCompletionInfo(contextToken);
|
||||
@ -2045,6 +2066,7 @@ namespace ts.Completions {
|
||||
// is not backward compatible with older clients, the language service defaults to disabling it, allowing newer clients
|
||||
// to opt in with the `includeCompletionsForImportStatements` user preference.
|
||||
importCompletionNode = importStatementCompletion.replacementNode;
|
||||
flags |= CompletionInfoFlags.IsImportStatementCompletion;
|
||||
}
|
||||
// Bail out if this is a known invalid completion location
|
||||
if (!importCompletionNode && isCompletionListBlocker(contextToken)) {
|
||||
@ -2252,6 +2274,7 @@ namespace ts.Completions {
|
||||
isRightOfOpenTag,
|
||||
importCompletionNode,
|
||||
hasUnresolvedAutoImports,
|
||||
flags,
|
||||
};
|
||||
|
||||
type JSDocTagWithTypeExpression = JSDocParameterTag | JSDocPropertyTag | JSDocReturnTag | JSDocTypeTag | JSDocTypedefTag | JSDocTemplateTag;
|
||||
@ -2692,6 +2715,7 @@ namespace ts.Completions {
|
||||
return;
|
||||
}
|
||||
|
||||
flags |= CompletionInfoFlags.MayIncludeAutoImports;
|
||||
// import { type | -> token text should be blank
|
||||
const isAfterTypeOnlyImportSpecifierModifier = previousToken === contextToken
|
||||
&& importCompletionNode
|
||||
@ -2736,14 +2760,34 @@ namespace ts.Completions {
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultExportInfo = find(info, isImportableExportInfo);
|
||||
if (!defaultExportInfo) {
|
||||
// Do a relatively cheap check to bail early if all re-exports are non-importable
|
||||
// due to file location or package.json dependency filtering. For non-node12+
|
||||
// module resolution modes, getting past this point guarantees that we'll be
|
||||
// able to generate a suitable module specifier, so we can safely show a completion,
|
||||
// even if we defer computing the module specifier.
|
||||
const firstImportableExportInfo = find(info, isImportableExportInfo);
|
||||
if (!firstImportableExportInfo) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't need to resolve module specifiers, we can use any re-export that is importable at all
|
||||
// (We need to ensure that at least one is importable to show a completion.)
|
||||
const { exportInfo = defaultExportInfo, moduleSpecifier } = context.tryResolve(info, symbolName, isFromAmbientModule) || {};
|
||||
// In node12+, module specifier resolution can fail due to modules being blocked
|
||||
// by package.json `exports`. If that happens, don't show a completion item.
|
||||
// N.B. in this resolution mode we always try to resolve module specifiers here,
|
||||
// because we have to know now if it's going to fail so we can omit the completion
|
||||
// from the list.
|
||||
const result = context.tryResolve(info, symbolName, isFromAmbientModule) || {};
|
||||
if (result === "failed") return;
|
||||
|
||||
// If we skipped resolving module specifiers, our selection of which ExportInfo
|
||||
// to use here is arbitrary, since the info shown in the completion list derived from
|
||||
// it should be identical regardless of which one is used. During the subsequent
|
||||
// `CompletionEntryDetails` request, we'll get all the ExportInfos again and pick
|
||||
// the best one based on the module specifier it produces.
|
||||
let exportInfo = firstImportableExportInfo, moduleSpecifier;
|
||||
if (result !== "skipped") {
|
||||
({ exportInfo = firstImportableExportInfo, moduleSpecifier } = result);
|
||||
}
|
||||
|
||||
const isDefaultExport = exportInfo.exportKind === ExportKind.Default;
|
||||
const symbol = isDefaultExport && getLocalSymbolForExportDefault(exportInfo.symbol) || exportInfo.symbol;
|
||||
|
||||
@ -2761,7 +2805,9 @@ namespace ts.Completions {
|
||||
}
|
||||
);
|
||||
|
||||
hasUnresolvedAutoImports = context.resolutionLimitExceeded();
|
||||
hasUnresolvedAutoImports = context.skippedAny();
|
||||
flags |= context.resolvedAny() ? CompletionInfoFlags.ResolvedModuleSpecifiers : 0;
|
||||
flags |= context.resolvedBeyondLimit() ? CompletionInfoFlags.ResolvedModuleSpecifiersBeyondLimit : 0;
|
||||
}
|
||||
);
|
||||
|
||||
@ -2831,6 +2877,7 @@ namespace ts.Completions {
|
||||
return;
|
||||
}
|
||||
const origin: SymbolOriginInfoObjectLiteralMethod = { kind: SymbolOriginInfoKind.ObjectLiteralMethod, ...entryProps };
|
||||
flags |= CompletionInfoFlags.MayIncludeMethodSnippets;
|
||||
symbolToOriginInfoMap[symbols.length] = origin;
|
||||
symbols.push(member);
|
||||
});
|
||||
|
||||
@ -291,8 +291,8 @@ namespace ts {
|
||||
): boolean {
|
||||
if (from === to) return false;
|
||||
const cachedResult = moduleSpecifierCache?.get(from.path, to.path, preferences, {});
|
||||
if (cachedResult?.isAutoImportable !== undefined) {
|
||||
return cachedResult.isAutoImportable;
|
||||
if (cachedResult?.isBlockedByPackageJsonDependencies !== undefined) {
|
||||
return !cachedResult.isBlockedByPackageJsonDependencies;
|
||||
}
|
||||
|
||||
const getCanonicalFileName = hostGetCanonicalFileName(moduleSpecifierResolutionHost);
|
||||
@ -313,7 +313,7 @@ namespace ts {
|
||||
|
||||
if (packageJsonFilter) {
|
||||
const isAutoImportable = hasImportablePath && packageJsonFilter.allowsImportingSourceFile(to, moduleSpecifierResolutionHost);
|
||||
moduleSpecifierCache?.setIsAutoImportable(from.path, to.path, preferences, {}, isAutoImportable);
|
||||
moduleSpecifierCache?.setBlockedByPackageJsonDependencies(from.path, to.path, preferences, {}, !isAutoImportable);
|
||||
return isAutoImportable;
|
||||
}
|
||||
|
||||
|
||||
@ -1176,7 +1176,20 @@ namespace ts {
|
||||
argumentCount: number;
|
||||
}
|
||||
|
||||
// Do not change existing values, as they exist in telemetry.
|
||||
export const enum CompletionInfoFlags {
|
||||
None = 0,
|
||||
MayIncludeAutoImports = 1 << 0,
|
||||
IsImportStatementCompletion = 1 << 1,
|
||||
IsContinuation = 1 << 2,
|
||||
ResolvedModuleSpecifiers = 1 << 3,
|
||||
ResolvedModuleSpecifiersBeyondLimit = 1 << 4,
|
||||
MayIncludeMethodSnippets = 1 << 5,
|
||||
}
|
||||
|
||||
export interface CompletionInfo {
|
||||
/** For performance telemetry. */
|
||||
flags?: CompletionInfoFlags;
|
||||
/** Not true for all global completions. This will be true if the enclosing scope matches a few syntax kinds. See `isSnippetScope`. */
|
||||
isGlobalCompletion: boolean;
|
||||
isMemberCompletion: boolean;
|
||||
|
||||
@ -1928,6 +1928,14 @@ namespace ts {
|
||||
};
|
||||
}
|
||||
|
||||
export function moduleResolutionRespectsExports(moduleResolution: ModuleResolutionKind): boolean {
|
||||
return moduleResolution >= ModuleResolutionKind.Node12 && moduleResolution <= ModuleResolutionKind.NodeNext;
|
||||
}
|
||||
|
||||
export function moduleResolutionUsesNodeModules(moduleResolution: ModuleResolutionKind): boolean {
|
||||
return moduleResolution === ModuleResolutionKind.NodeJs || moduleResolution >= ModuleResolutionKind.Node12 && moduleResolution <= ModuleResolutionKind.NodeNext;
|
||||
}
|
||||
|
||||
export function makeImportIfNecessary(defaultImport: Identifier | undefined, namedImports: readonly ImportSpecifier[] | undefined, moduleSpecifier: string, quotePreference: QuotePreference): ImportDeclaration | undefined {
|
||||
return defaultImport || namedImports && namedImports.length ? makeImport(defaultImport, namedImports, moduleSpecifier, quotePreference) : undefined;
|
||||
}
|
||||
|
||||
@ -52,6 +52,7 @@ namespace ts.projectSystem {
|
||||
assert.isString(exportMapKey);
|
||||
delete (response?.entries[0].data as any).exportMapKey;
|
||||
assert.deepEqual<protocol.CompletionInfo | undefined>(response, {
|
||||
flags: CompletionInfoFlags.MayIncludeAutoImports,
|
||||
isGlobalCompletion: true,
|
||||
isIncomplete: undefined,
|
||||
isMemberCompletion: false,
|
||||
|
||||
@ -77,6 +77,7 @@ namespace ts.projectSystem {
|
||||
command: protocol.CommandTypes.CompletionInfo,
|
||||
arguments: completionRequestArgs
|
||||
}, {
|
||||
flags: 0,
|
||||
isGlobalCompletion: false,
|
||||
isMemberCompletion: true,
|
||||
isNewIdentifierLocation: false,
|
||||
|
||||
@ -39,7 +39,7 @@ namespace ts.projectSystem {
|
||||
describe("unittests:: tsserver:: moduleSpecifierCache", () => {
|
||||
it("caches importability within a file", () => {
|
||||
const { moduleSpecifierCache } = setup();
|
||||
assert.isTrue(moduleSpecifierCache.get(bTs.path as Path, aTs.path as Path, {}, {})?.isAutoImportable);
|
||||
assert.isFalse(moduleSpecifierCache.get(bTs.path as Path, aTs.path as Path, {}, {})?.isBlockedByPackageJsonDependencies);
|
||||
});
|
||||
|
||||
it("caches module specifiers within a file", () => {
|
||||
@ -54,7 +54,7 @@ namespace ts.projectSystem {
|
||||
isRedirect: false
|
||||
}],
|
||||
moduleSpecifiers: ["mobx"],
|
||||
isAutoImportable: true,
|
||||
isBlockedByPackageJsonDependencies: false,
|
||||
});
|
||||
});
|
||||
|
||||
@ -72,7 +72,7 @@ namespace ts.projectSystem {
|
||||
const { host, moduleSpecifierCache } = setup();
|
||||
host.writeFile("/src/a2.ts", aTs.content);
|
||||
host.runQueuedTimeoutCallbacks();
|
||||
assert.isTrue(moduleSpecifierCache.get(bTs.path as Path, aTs.path as Path, {}, {})?.isAutoImportable);
|
||||
assert.isFalse(moduleSpecifierCache.get(bTs.path as Path, aTs.path as Path, {}, {})?.isBlockedByPackageJsonDependencies);
|
||||
});
|
||||
|
||||
it("invalidates the cache when symlinks are added or removed", () => {
|
||||
|
||||
@ -6435,7 +6435,18 @@ declare namespace ts {
|
||||
argumentIndex: number;
|
||||
argumentCount: number;
|
||||
}
|
||||
enum CompletionInfoFlags {
|
||||
None = 0,
|
||||
MayIncludeAutoImports = 1,
|
||||
IsImportStatementCompletion = 2,
|
||||
IsContinuation = 4,
|
||||
ResolvedModuleSpecifiers = 8,
|
||||
ResolvedModuleSpecifiersBeyondLimit = 16,
|
||||
MayIncludeMethodSnippets = 32
|
||||
}
|
||||
interface CompletionInfo {
|
||||
/** For performance telemetry. */
|
||||
flags?: CompletionInfoFlags;
|
||||
/** Not true for all global completions. This will be true if the enclosing scope matches a few syntax kinds. See `isSnippetScope`. */
|
||||
isGlobalCompletion: boolean;
|
||||
isMemberCompletion: boolean;
|
||||
@ -8823,6 +8834,7 @@ declare namespace ts.server.protocol {
|
||||
body?: CompletionInfo;
|
||||
}
|
||||
interface CompletionInfo {
|
||||
readonly flags?: number;
|
||||
readonly isGlobalCompletion: boolean;
|
||||
readonly isMemberCompletion: boolean;
|
||||
readonly isNewIdentifierLocation: boolean;
|
||||
|
||||
11
tests/baselines/reference/api/typescript.d.ts
vendored
11
tests/baselines/reference/api/typescript.d.ts
vendored
@ -6435,7 +6435,18 @@ declare namespace ts {
|
||||
argumentIndex: number;
|
||||
argumentCount: number;
|
||||
}
|
||||
enum CompletionInfoFlags {
|
||||
None = 0,
|
||||
MayIncludeAutoImports = 1,
|
||||
IsImportStatementCompletion = 2,
|
||||
IsContinuation = 4,
|
||||
ResolvedModuleSpecifiers = 8,
|
||||
ResolvedModuleSpecifiersBeyondLimit = 16,
|
||||
MayIncludeMethodSnippets = 32
|
||||
}
|
||||
interface CompletionInfo {
|
||||
/** For performance telemetry. */
|
||||
flags?: CompletionInfoFlags;
|
||||
/** Not true for all global completions. This will be true if the enclosing scope matches a few syntax kinds. See `isSnippetScope`. */
|
||||
isGlobalCompletion: boolean;
|
||||
isMemberCompletion: boolean;
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": ""
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "0"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -73,6 +74,7 @@
|
||||
"name": "1"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "26"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "4"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -754,6 +755,7 @@
|
||||
"name": "5"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -4818,6 +4820,7 @@
|
||||
"name": "7"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -5566,6 +5569,7 @@
|
||||
"name": "9"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -6314,6 +6318,7 @@
|
||||
"name": "11"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -7062,6 +7067,7 @@
|
||||
"name": "12"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -7810,6 +7816,7 @@
|
||||
"name": "13"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -11874,6 +11881,7 @@
|
||||
"name": "16"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -12622,6 +12630,7 @@
|
||||
"name": "17"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -16686,6 +16695,7 @@
|
||||
"name": "19"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -17434,6 +17444,7 @@
|
||||
"name": "21"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -18182,6 +18193,7 @@
|
||||
"name": "23"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -18930,6 +18942,7 @@
|
||||
"name": "24"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -19678,6 +19691,7 @@
|
||||
"name": "25"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -23742,6 +23756,7 @@
|
||||
"name": "29"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -27806,6 +27821,7 @@
|
||||
"name": "30"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -28961,6 +28977,7 @@
|
||||
"name": "31"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -33025,6 +33042,7 @@
|
||||
"name": "33"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -37043,6 +37061,7 @@
|
||||
"name": "34"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -38198,6 +38217,7 @@
|
||||
"name": "35"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -42216,6 +42236,7 @@
|
||||
"name": "36"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -43371,6 +43392,7 @@
|
||||
"name": "38"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -47435,6 +47457,7 @@
|
||||
"name": "39"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -48590,6 +48613,7 @@
|
||||
"name": "40"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -52654,6 +52678,7 @@
|
||||
"name": "41"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -53809,6 +53834,7 @@
|
||||
"name": "42"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -57873,6 +57899,7 @@
|
||||
"name": "45"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -61932,6 +61959,7 @@
|
||||
"name": "49"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -65991,6 +66019,7 @@
|
||||
"name": "52"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -70050,6 +70079,7 @@
|
||||
"name": "56"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -74109,6 +74139,7 @@
|
||||
"name": "59"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -78168,6 +78199,7 @@
|
||||
"name": "63"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -82227,6 +82259,7 @@
|
||||
"name": "67"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -82610,6 +82643,7 @@
|
||||
"name": "87"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -86782,6 +86816,7 @@
|
||||
"name": "88"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -87937,6 +87972,7 @@
|
||||
"name": "109"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -92138,6 +92174,7 @@
|
||||
"name": "110"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -92362,6 +92399,7 @@
|
||||
"name": "114"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -92461,6 +92499,7 @@
|
||||
"name": "115"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "18"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -5653,6 +5654,7 @@
|
||||
"name": "15"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -12096,6 +12098,7 @@
|
||||
"name": "24"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -17719,6 +17722,7 @@
|
||||
"name": "27"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -23419,6 +23423,7 @@
|
||||
"name": "39"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -29161,6 +29166,7 @@
|
||||
"name": "44"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -35604,6 +35610,7 @@
|
||||
"name": ""
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "3"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -4316,6 +4317,7 @@
|
||||
"name": "7"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": true,
|
||||
@ -7792,6 +7794,7 @@
|
||||
"name": "9"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "2"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -3853,6 +3854,7 @@
|
||||
"name": "4"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -8575,6 +8577,7 @@
|
||||
"name": "15"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
@ -12241,6 +12244,7 @@
|
||||
"name": "17"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": true,
|
||||
"isMemberCompletion": false,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "14"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "2"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
"name": "1"
|
||||
},
|
||||
"completionList": {
|
||||
"flags": 0,
|
||||
"isGlobalCompletion": false,
|
||||
"isMemberCompletion": true,
|
||||
"isNewIdentifierLocation": false,
|
||||
|
||||
35
tests/cases/fourslash/autoImportsNodeNext1.ts
Normal file
35
tests/cases/fourslash/autoImportsNodeNext1.ts
Normal file
@ -0,0 +1,35 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @module: nodenext
|
||||
|
||||
// @Filename: /node_modules/pack/package.json
|
||||
//// {
|
||||
//// "name": "pack",
|
||||
//// "version": "1.0.0",
|
||||
//// "exports": {
|
||||
//// ".": "./main.mjs"
|
||||
//// }
|
||||
//// }
|
||||
|
||||
// @Filename: /node_modules/pack/main.d.mts
|
||||
//// import {} from "./unreachable.mjs";
|
||||
//// export const fromMain = 0;
|
||||
|
||||
// @Filename: /node_modules/pack/unreachable.d.mts
|
||||
//// export const fromUnreachable = 0;
|
||||
|
||||
// @Filename: /index.mts
|
||||
//// import { fromMain } from "pack";
|
||||
//// fromUnreachable/**/
|
||||
|
||||
goTo.marker("");
|
||||
verify.importFixAtPosition([]);
|
||||
|
||||
verify.completions({
|
||||
marker: "",
|
||||
excludes: ["fromUnreachable"],
|
||||
preferences: {
|
||||
includeCompletionsForModuleExports: true,
|
||||
allowIncompleteCompletions: false,
|
||||
}
|
||||
});
|
||||
@ -39,16 +39,6 @@ goTo.marker("");
|
||||
verify.completions({
|
||||
marker: "",
|
||||
exact: completion.globalsPlus([{
|
||||
// TODO: We should filter this one out due to its bad module specifier,
|
||||
// but we don't know it's going to be filtered out until we actually
|
||||
// resolve the module specifier, which is a problem for completions
|
||||
// that don't have their module specifiers eagerly resolved.
|
||||
name: "fooFromIndex",
|
||||
source: "../node_modules/dependency/lib/index.js",
|
||||
sourceDisplay: "../node_modules/dependency/lib/index.js",
|
||||
sortText: completion.SortText.AutoImportSuggestions,
|
||||
hasAction: true,
|
||||
}, {
|
||||
name: "fooFromLol",
|
||||
source: "dependency",
|
||||
sourceDisplay: "dependency",
|
||||
|
||||
@ -49,13 +49,6 @@ goTo.marker("cts");
|
||||
verify.completions({
|
||||
marker: "cts",
|
||||
exact: completion.globalsPlus([{
|
||||
// TODO: this one will go away (see note in ./autoImportProvider_exportMap3.ts)
|
||||
name: "fooFromIndex",
|
||||
source: "../node_modules/dependency/lib/index",
|
||||
sourceDisplay: "../node_modules/dependency/lib/index",
|
||||
sortText: completion.SortText.AutoImportSuggestions,
|
||||
hasAction: true,
|
||||
}, {
|
||||
name: "fooFromLol",
|
||||
source: "dependency/lol",
|
||||
sourceDisplay: "dependency/lol",
|
||||
@ -78,13 +71,6 @@ verify.completions({
|
||||
sourceDisplay: "dependency/lol",
|
||||
sortText: completion.SortText.AutoImportSuggestions,
|
||||
hasAction: true,
|
||||
}, {
|
||||
// TODO: this one will go away (see note in ./autoImportProvider_exportMap3.ts)
|
||||
name: "fooFromLol",
|
||||
source: "../node_modules/dependency/lib/lol.js",
|
||||
sourceDisplay: "../node_modules/dependency/lib/lol.js",
|
||||
sortText: completion.SortText.AutoImportSuggestions,
|
||||
hasAction: true,
|
||||
}]),
|
||||
preferences: {
|
||||
includeCompletionsForModuleExports: true,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user