From 4d2983a7362f8fab69cc68c6508929a95dc4f3f4 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Thu, 9 Jun 2022 11:05:04 -0700 Subject: [PATCH 1/3] Cherry-pick PR #49442 into release-4.7 (#49447) Component commits: d8f251b90a Avoid repeating codefix work when resolving auto-import specifiers for completions Co-authored-by: Andrew Branch --- src/services/codefixes/importFixes.ts | 106 +++++++++++++++++--------- src/services/completions.ts | 16 ++-- 2 files changed, 78 insertions(+), 44 deletions(-) diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 5f9080201686d..9ed9bbec0ea85 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -40,6 +40,9 @@ namespace ts.codefix { }, }); + /** + * Computes multiple import additions to a file and writes them to a ChangeTracker. + */ export interface ImportAdder { hasFixes(): boolean; addImportFromDiagnostic: (diagnostic: DiagnosticWithLocation, context: CodeFixContextBase) => void; @@ -235,6 +238,47 @@ namespace ts.codefix { } } + /** + * Computes module specifiers for multiple import additions to a file. + */ + export interface ImportSpecifierResolver { + getModuleSpecifierForBestExportInfo( + exportInfo: readonly SymbolExportInfo[], + symbolName: string, + position: number, + isValidTypeOnlyUseSite: boolean, + fromCacheOnly?: boolean + ): { exportInfo?: SymbolExportInfo, moduleSpecifier: string, computedWithoutCacheCount: number } | undefined; + } + + export function createImportSpecifierResolver(importingFile: SourceFile, program: Program, host: LanguageServiceHost, preferences: UserPreferences): ImportSpecifierResolver { + const packageJsonImportFilter = createPackageJsonImportFilter(importingFile, preferences, host); + const importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); + return { getModuleSpecifierForBestExportInfo }; + + function getModuleSpecifierForBestExportInfo( + exportInfo: readonly SymbolExportInfo[], + symbolName: string, + position: number, + isValidTypeOnlyUseSite: boolean, + fromCacheOnly?: boolean, + ): { exportInfo?: SymbolExportInfo, moduleSpecifier: string, computedWithoutCacheCount: number } | undefined { + const { fixes, computedWithoutCacheCount } = getImportFixes( + exportInfo, + { symbolName, position }, + isValidTypeOnlyUseSite, + /*useRequire*/ false, + program, + importingFile, + host, + preferences, + importMap, + fromCacheOnly); + const result = getBestFix(fixes, importingFile, program, packageJsonImportFilter, host); + return result && { ...result, computedWithoutCacheCount }; + } + } + // Sorted with the preferred fix coming first. const enum ImportFixKind { UseNamespace, JsdocTypeImport, AddToExisting, AddNew, PromoteTypeOnly } // These should not be combined as bitflags, but are given powers of 2 values to @@ -394,32 +438,6 @@ namespace ts.codefix { } } - export function getModuleSpecifierForBestExportInfo( - exportInfo: readonly SymbolExportInfo[], - symbolName: string, - position: number, - isValidTypeOnlyUseSite: boolean, - importingFile: SourceFile, - program: Program, - host: LanguageServiceHost, - preferences: UserPreferences, - packageJsonImportFilter?: PackageJsonImportFilter, - fromCacheOnly?: boolean, - ): { exportInfo?: SymbolExportInfo, moduleSpecifier: string, computedWithoutCacheCount: number } | undefined { - const { fixes, computedWithoutCacheCount } = getImportFixes( - exportInfo, - { symbolName, position }, - isValidTypeOnlyUseSite, - /*useRequire*/ false, - program, - importingFile, - host, - preferences, - fromCacheOnly); - const result = getBestFix(fixes, importingFile, program, packageJsonImportFilter || createPackageJsonImportFilter(importingFile, preferences, host), host); - return result && { ...result, computedWithoutCacheCount }; - } - function getImportFixes( exportInfos: readonly SymbolExportInfo[], useNamespaceInfo: { @@ -433,10 +451,11 @@ namespace ts.codefix { sourceFile: SourceFile, host: LanguageServiceHost, preferences: UserPreferences, + importMap = createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()), fromCacheOnly?: boolean, ): { computedWithoutCacheCount: number, fixes: readonly ImportFixWithModuleSpecifier[] } { const checker = program.getTypeChecker(); - const existingImports = flatMap(exportInfos, info => getExistingImportDeclarations(info, checker, sourceFile, program.getCompilerOptions())); + const existingImports = flatMap(exportInfos, importMap.getImportsForExportInfo); const useNamespace = useNamespaceInfo && tryUseExistingNamespaceImport(existingImports, useNamespaceInfo.symbolName, useNamespaceInfo.position, checker); const addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions()); if (addToExisting) { @@ -587,19 +606,34 @@ namespace ts.codefix { }); } - function getExistingImportDeclarations({ moduleSymbol, exportKind, targetFlags, symbol }: SymbolExportInfo, checker: TypeChecker, importingFile: SourceFile, compilerOptions: CompilerOptions): readonly FixAddToExistingImportInfo[] { - // Can't use an es6 import for a type in JS. - if (!(targetFlags & SymbolFlags.Value) && isSourceFileJS(importingFile)) return emptyArray; - const importKind = getImportKind(importingFile, exportKind, compilerOptions); - return mapDefined(importingFile.imports, (moduleSpecifier): FixAddToExistingImportInfo | undefined => { + function createExistingImportMap(checker: TypeChecker, importingFile: SourceFile, compilerOptions: CompilerOptions) { + let importMap: MultiMap | undefined; + for (const moduleSpecifier of importingFile.imports) { const i = importFromModuleSpecifier(moduleSpecifier); if (isVariableDeclarationInitializedToRequire(i.parent)) { - return checker.resolveExternalModuleName(moduleSpecifier) === moduleSymbol ? { declaration: i.parent, importKind, symbol, targetFlags } : undefined; + const moduleSymbol = checker.resolveExternalModuleName(moduleSpecifier); + if (moduleSymbol) { + (importMap ||= createMultiMap()).add(getSymbolId(moduleSymbol), i.parent); + } } - if (i.kind === SyntaxKind.ImportDeclaration || i.kind === SyntaxKind.ImportEqualsDeclaration) { - return checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind, symbol, targetFlags } : undefined; + else if (i.kind === SyntaxKind.ImportDeclaration || i.kind === SyntaxKind.ImportEqualsDeclaration) { + const moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); + if (moduleSymbol) { + (importMap ||= createMultiMap()).add(getSymbolId(moduleSymbol), i); + } } - }); + } + + return { + getImportsForExportInfo: ({ moduleSymbol, exportKind, targetFlags, symbol }: SymbolExportInfo): readonly FixAddToExistingImportInfo[] => { + // Can't use an es6 import for a type in JS. + if (!(targetFlags & SymbolFlags.Value) && isSourceFileJS(importingFile)) return emptyArray; + const matchingDeclarations = importMap?.get(getSymbolId(moduleSymbol)); + if (!matchingDeclarations) return emptyArray; + const importKind = getImportKind(importingFile, exportKind, compilerOptions); + return matchingDeclarations.map(declaration => ({ declaration, importKind, symbol, targetFlags })); + } + }; } function shouldUseRequire(sourceFile: SourceFile, program: Program): boolean { diff --git a/src/services/completions.ts b/src/services/completions.ts index 27066f7b72e64..8727ca2f1b3c9 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -184,8 +184,8 @@ namespace ts.Completions { function resolvingModuleSpecifiers( logPrefix: string, host: LanguageServiceHost, + resolver: codefix.ImportSpecifierResolver, program: Program, - sourceFile: SourceFile, position: number, preferences: UserPreferences, isForImportStatementCompletion: boolean, @@ -193,7 +193,6 @@ namespace ts.Completions { cb: (context: ModuleSpecifierResolutioContext) => TReturn, ): TReturn { const start = timestamp(); - const packageJsonImportFilter = createPackageJsonImportFilter(sourceFile, preferences, host); // 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. @@ -221,7 +220,7 @@ namespace ts.Completions { function tryResolve(exportInfo: readonly SymbolExportInfo[], symbolName: string, isFromAmbientModule: boolean): ModuleSpecifierResolutionResult { if (isFromAmbientModule) { - const result = codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences); + const result = resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite); if (result) { ambientCount++; } @@ -230,7 +229,7 @@ namespace ts.Completions { 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) + ? resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, shouldGetModuleSpecifierFromCache) : undefined; if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) { @@ -371,8 +370,8 @@ namespace ts.Completions { const newEntries = resolvingModuleSpecifiers( "continuePreviousIncompleteResponse", host, + codefix.createImportSpecifierResolver(file, program, host, preferences), program, - file, location.getStart(), preferences, /*isForImportStatementCompletion*/ false, @@ -2206,6 +2205,7 @@ namespace ts.Completions { let hasUnresolvedAutoImports = false; // This also gets mutated in nested-functions after the return let symbols: Symbol[] = []; + let importSpecifierResolver: codefix.ImportSpecifierResolver | undefined; const symbolToOriginInfoMap: SymbolOriginInfoMap = []; const symbolToSortTextMap: SymbolSortTextMap = []; const seenPropertySymbols = new Map(); @@ -2448,14 +2448,14 @@ namespace ts.Completions { } else { const fileName = isExternalModuleNameRelative(stripQuotes(moduleSymbol.name)) ? getSourceFileOfModule(moduleSymbol)?.fileName : undefined; - const { moduleSpecifier } = codefix.getModuleSpecifierForBestExportInfo([{ + const { moduleSpecifier } = (importSpecifierResolver ||= codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)).getModuleSpecifierForBestExportInfo([{ exportKind: ExportKind.Named, moduleFileName: fileName, isFromPackageJson: false, moduleSymbol, symbol: firstAccessibleSymbol, targetFlags: skipAlias(firstAccessibleSymbol, typeChecker).flags, - }], firstAccessibleSymbol.name, position, isValidTypeOnlyAliasUseSite(location), sourceFile, program, host, preferences) || {}; + }], firstAccessibleSymbol.name, position, isValidTypeOnlyAliasUseSite(location)) || {}; if (moduleSpecifier) { const origin: SymbolOriginInfoResolvedExport = { @@ -2733,8 +2733,8 @@ namespace ts.Completions { resolvingModuleSpecifiers( "collectAutoImports", host, + importSpecifierResolver ||= codefix.createImportSpecifierResolver(sourceFile, program, host, preferences), program, - sourceFile, position, preferences, !!importCompletionNode, From dfe885b302dc6f8f2753b9b58a8de5a519c5c98e Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 16 Jun 2022 10:43:47 -0700 Subject: [PATCH 2/3] Properly re-scan `>` token in type argument list determination logic (#49560) (#49570) * Properly re-scan '>' token in type argument list determination logic * Add regression test --- src/compiler/parser.ts | 3 +- .../instantiationExpressionErrors.errors.txt | 144 +++++++++++++- .../instantiationExpressionErrors.js | 127 +++++++++++++ .../instantiationExpressionErrors.symbols | 117 ++++++++++++ .../instantiationExpressionErrors.types | 178 ++++++++++++++++++ .../instantiationExpressionErrors.ts | 47 +++++ 6 files changed, 614 insertions(+), 2 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 35536bb224628..7f124465f5605 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -5705,10 +5705,11 @@ namespace ts { nextToken(); const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType); - if (!parseExpected(SyntaxKind.GreaterThanToken)) { + if (reScanGreaterToken() !== SyntaxKind.GreaterThanToken) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + nextToken(); // We successfully parsed a type argument list. The next token determines whether we want to // treat it as such. If the type argument list is followed by `(` or a template literal, as in diff --git a/tests/baselines/reference/instantiationExpressionErrors.errors.txt b/tests/baselines/reference/instantiationExpressionErrors.errors.txt index 5b60983d594dc..ca9a48661f775 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.errors.txt +++ b/tests/baselines/reference/instantiationExpressionErrors.errors.txt @@ -8,9 +8,40 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpr tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(26,24): error TS2558: Expected 0 type arguments, but got 1. tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(31,2): error TS2554: Expected 0 arguments, but got 1. tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(35,12): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(48,12): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(49,1): error TS2304: Cannot find name 'let'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(49,5): error TS1005: ',' expected. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(51,12): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(52,1): error TS2304: Cannot find name 'interface'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(52,11): error TS1005: ',' expected. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(52,11): error TS7005: Variable 'I' implicitly has an 'any' type. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(52,13): error TS1005: ',' expected. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(54,11): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(55,6): error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(57,11): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(57,11): error TS2365: Operator '>' cannot be applied to types 'boolean' and '() => void'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(60,11): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(60,11): error TS2365: Operator '>' cannot be applied to types 'boolean' and 'typeof C'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(63,11): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(64,1): error TS2304: Cannot find name 'bar'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(66,11): error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(67,1): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(67,6): error TS2304: Cannot find name 'bar'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(70,27): error TS2693: 'string' only refers to a type, but is being used as a value here. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(71,5): error TS2304: Cannot find name 'static'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(71,12): error TS1005: ';' expected. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(75,27): error TS2693: 'string' only refers to a type, but is being used as a value here. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(76,5): error TS2304: Cannot find name 'public'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(76,12): error TS1005: ';' expected. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(80,28): error TS2693: 'string' only refers to a type, but is being used as a value here. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(81,5): error TS2304: Cannot find name 'private'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(81,13): error TS1005: ';' expected. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(85,30): error TS2693: 'string' only refers to a type, but is being used as a value here. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(86,5): error TS2304: Cannot find name 'protected'. +tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts(86,15): error TS1005: ';' expected. -==== tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts (10 errors) ==== +==== tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts (41 errors) ==== declare let f: { (): T, g(): U }; // Type arguments in member expressions @@ -77,4 +108,115 @@ tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpr const x4 = f if (true) {} + + const x5 = f + ~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. + let yy = 0; + ~~~ +!!! error TS2304: Cannot find name 'let'. + ~~ +!!! error TS1005: ',' expected. + + const x6 = f + ~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. + interface I {} + ~~~~~~~~~ +!!! error TS2304: Cannot find name 'interface'. + ~ +!!! error TS1005: ',' expected. + ~ +!!! error TS7005: Variable 'I' implicitly has an 'any' type. + ~ +!!! error TS1005: ',' expected. + + let x10 = f + ~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. + this.bar() + ~~~ +!!! error TS7017: Element implicitly has an 'any' type because type 'typeof globalThis' has no index signature. + + let x11 = f + ~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. + ~~~~~~~ + function bar() {} + ~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and '() => void'. + + let x12 = f + ~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. + ~~~~~~~ + class C {} + ~~~~~~~~~~ +!!! error TS2365: Operator '>' cannot be applied to types 'boolean' and 'typeof C'. + + let x13 = f + ~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. + bar() + ~~~ +!!! error TS2304: Cannot find name 'bar'. + + let x14 = f + ~~~~~~ +!!! error TS2365: Operator '<' cannot be applied to types '{ (): T; g(): U; }' and 'boolean'. + void bar() + ~~~~~~~~~~ +!!! error TS2532: Object is possibly 'undefined'. + ~~~ +!!! error TS2304: Cannot find name 'bar'. + + class C1 { + static specialFoo = f + ~~~~~~ +!!! error TS2693: 'string' only refers to a type, but is being used as a value here. + static bar = 123 + ~~~~~~ +!!! error TS2304: Cannot find name 'static'. + ~~~ +!!! error TS1005: ';' expected. + } + + class C2 { + public specialFoo = f + ~~~~~~ +!!! error TS2693: 'string' only refers to a type, but is being used as a value here. + public bar = 123 + ~~~~~~ +!!! error TS2304: Cannot find name 'public'. + ~~~ +!!! error TS1005: ';' expected. + } + + class C3 { + private specialFoo = f + ~~~~~~ +!!! error TS2693: 'string' only refers to a type, but is being used as a value here. + private bar = 123 + ~~~~~~~ +!!! error TS2304: Cannot find name 'private'. + ~~~ +!!! error TS1005: ';' expected. + } + + class C4 { + protected specialFoo = f + ~~~~~~ +!!! error TS2693: 'string' only refers to a type, but is being used as a value here. + protected bar = 123 + ~~~~~~~~~ +!!! error TS2304: Cannot find name 'protected'. + ~~~ +!!! error TS1005: ';' expected. + } + + // Repro from #49551 + + const enum MyVer { v1 = 1, v2 = 2 } + let ver = 21 + const a = ver < (MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2) \ No newline at end of file diff --git a/tests/baselines/reference/instantiationExpressionErrors.js b/tests/baselines/reference/instantiationExpressionErrors.js index 9f6b17f13787a..54601147d8bdb 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.js +++ b/tests/baselines/reference/instantiationExpressionErrors.js @@ -45,6 +45,53 @@ true; const x4 = f if (true) {} + +const x5 = f +let yy = 0; + +const x6 = f +interface I {} + +let x10 = f +this.bar() + +let x11 = f +function bar() {} + +let x12 = f +class C {} + +let x13 = f +bar() + +let x14 = f +void bar() + +class C1 { + static specialFoo = f + static bar = 123 +} + +class C2 { + public specialFoo = f + public bar = 123 +} + +class C3 { + private specialFoo = f + private bar = 123 +} + +class C4 { + protected specialFoo = f + protected bar = 123 +} + +// Repro from #49551 + +const enum MyVer { v1 = 1, v2 = 2 } +let ver = 21 +const a = ver < (MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2) //// [instantiationExpressionErrors.js] @@ -78,6 +125,57 @@ true; // Parsed as instantiation expression var x4 = (f); if (true) { } +var x5 = f < true > + let, yy = 0; +var x6 = f < true > + interface, I, _c = void 0; +var x10 = f < true > + this.bar(); +var x11 = f < true > + function bar() { }; +var x12 = f < true > /** @class */ (function () { + function C() { + } + return C; +}()); +var x13 = f < true > + bar(); +var x14 = f < true > + void bar(); +var C1 = /** @class */ (function () { + function C1() { + this.bar = 123; + } + C1.specialFoo = f < string > + static; + return C1; +}()); +var C2 = /** @class */ (function () { + function C2() { + this.specialFoo = f < string > + public; + this.bar = 123; + } + return C2; +}()); +var C3 = /** @class */ (function () { + function C3() { + this.specialFoo = f < string > + private; + this.bar = 123; + } + return C3; +}()); +var C4 = /** @class */ (function () { + function C4() { + this.specialFoo = f < string > + protected; + this.bar = 123; + } + return C4; +}()); +var ver = 21; +var a = ver < (1 /* MyVer.v1 */ >= 2 /* MyVer.v2 */ ? 1 /* MyVer.v1 */ : 2 /* MyVer.v2 */); //// [instantiationExpressionErrors.d.ts] @@ -113,3 +211,32 @@ declare const x4: { (): true; g(): U; }; +declare const x5: boolean, yy = 0; +declare const x6: boolean, I: any; +declare let x10: boolean; +declare let x11: boolean; +declare let x12: boolean; +declare let x13: boolean; +declare let x14: boolean; +declare class C1 { + static specialFoo: boolean; + bar: number; +} +declare class C2 { + specialFoo: boolean; + bar: number; +} +declare class C3 { + private specialFoo; + bar: number; +} +declare class C4 { + protected specialFoo: boolean; + bar: number; +} +declare const enum MyVer { + v1 = 1, + v2 = 2 +} +declare let ver: number; +declare const a: boolean; diff --git a/tests/baselines/reference/instantiationExpressionErrors.symbols b/tests/baselines/reference/instantiationExpressionErrors.symbols index dc1e6d5d64b3c..41dc8aaed1198 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.symbols +++ b/tests/baselines/reference/instantiationExpressionErrors.symbols @@ -107,3 +107,120 @@ const x4 = f if (true) {} +const x5 = f +>x5 : Symbol(x5, Decl(instantiationExpressionErrors.ts, 47, 5)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +let yy = 0; +>yy : Symbol(yy, Decl(instantiationExpressionErrors.ts, 48, 3)) + +const x6 = f +>x6 : Symbol(x6, Decl(instantiationExpressionErrors.ts, 50, 5)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +interface I {} +>I : Symbol(I, Decl(instantiationExpressionErrors.ts, 51, 9)) + +let x10 = f +>x10 : Symbol(x10, Decl(instantiationExpressionErrors.ts, 53, 3)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +this.bar() +>this : Symbol(globalThis) + +let x11 = f +>x11 : Symbol(x11, Decl(instantiationExpressionErrors.ts, 56, 3)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +function bar() {} +>bar : Symbol(bar, Decl(instantiationExpressionErrors.ts, 56, 17)) + +let x12 = f +>x12 : Symbol(x12, Decl(instantiationExpressionErrors.ts, 59, 3)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +class C {} +>C : Symbol(C, Decl(instantiationExpressionErrors.ts, 59, 17)) + +let x13 = f +>x13 : Symbol(x13, Decl(instantiationExpressionErrors.ts, 62, 3)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +bar() + +let x14 = f +>x14 : Symbol(x14, Decl(instantiationExpressionErrors.ts, 65, 3)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + +void bar() + +class C1 { +>C1 : Symbol(C1, Decl(instantiationExpressionErrors.ts, 66, 10)) + + static specialFoo = f +>specialFoo : Symbol(C1.specialFoo, Decl(instantiationExpressionErrors.ts, 68, 10)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + + static bar = 123 +>bar : Symbol(C1.bar, Decl(instantiationExpressionErrors.ts, 70, 10)) +} + +class C2 { +>C2 : Symbol(C2, Decl(instantiationExpressionErrors.ts, 71, 1)) + + public specialFoo = f +>specialFoo : Symbol(C2.specialFoo, Decl(instantiationExpressionErrors.ts, 73, 10)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + + public bar = 123 +>bar : Symbol(C2.bar, Decl(instantiationExpressionErrors.ts, 75, 10)) +} + +class C3 { +>C3 : Symbol(C3, Decl(instantiationExpressionErrors.ts, 76, 1)) + + private specialFoo = f +>specialFoo : Symbol(C3.specialFoo, Decl(instantiationExpressionErrors.ts, 78, 10)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + + private bar = 123 +>bar : Symbol(C3.bar, Decl(instantiationExpressionErrors.ts, 80, 11)) +} + +class C4 { +>C4 : Symbol(C4, Decl(instantiationExpressionErrors.ts, 81, 1)) + + protected specialFoo = f +>specialFoo : Symbol(C4.specialFoo, Decl(instantiationExpressionErrors.ts, 83, 10)) +>f : Symbol(f, Decl(instantiationExpressionErrors.ts, 0, 11)) + + protected bar = 123 +>bar : Symbol(C4.bar, Decl(instantiationExpressionErrors.ts, 85, 13)) +} + +// Repro from #49551 + +const enum MyVer { v1 = 1, v2 = 2 } +>MyVer : Symbol(MyVer, Decl(instantiationExpressionErrors.ts, 86, 1)) +>v1 : Symbol(MyVer.v1, Decl(instantiationExpressionErrors.ts, 90, 18)) +>v2 : Symbol(MyVer.v2, Decl(instantiationExpressionErrors.ts, 90, 26)) + +let ver = 21 +>ver : Symbol(ver, Decl(instantiationExpressionErrors.ts, 91, 3)) + +const a = ver < (MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2) +>a : Symbol(a, Decl(instantiationExpressionErrors.ts, 92, 5)) +>ver : Symbol(ver, Decl(instantiationExpressionErrors.ts, 91, 3)) +>MyVer.v1 : Symbol(MyVer.v1, Decl(instantiationExpressionErrors.ts, 90, 18)) +>MyVer : Symbol(MyVer, Decl(instantiationExpressionErrors.ts, 86, 1)) +>v1 : Symbol(MyVer.v1, Decl(instantiationExpressionErrors.ts, 90, 18)) +>MyVer.v2 : Symbol(MyVer.v2, Decl(instantiationExpressionErrors.ts, 90, 26)) +>MyVer : Symbol(MyVer, Decl(instantiationExpressionErrors.ts, 86, 1)) +>v2 : Symbol(MyVer.v2, Decl(instantiationExpressionErrors.ts, 90, 26)) +>MyVer.v1 : Symbol(MyVer.v1, Decl(instantiationExpressionErrors.ts, 90, 18)) +>MyVer : Symbol(MyVer, Decl(instantiationExpressionErrors.ts, 86, 1)) +>v1 : Symbol(MyVer.v1, Decl(instantiationExpressionErrors.ts, 90, 18)) +>MyVer.v2 : Symbol(MyVer.v2, Decl(instantiationExpressionErrors.ts, 90, 26)) +>MyVer : Symbol(MyVer, Decl(instantiationExpressionErrors.ts, 86, 1)) +>v2 : Symbol(MyVer.v2, Decl(instantiationExpressionErrors.ts, 90, 26)) + diff --git a/tests/baselines/reference/instantiationExpressionErrors.types b/tests/baselines/reference/instantiationExpressionErrors.types index c2de6b5720ec1..1d6e484b80eb1 100644 --- a/tests/baselines/reference/instantiationExpressionErrors.types +++ b/tests/baselines/reference/instantiationExpressionErrors.types @@ -145,3 +145,181 @@ const x4 = f if (true) {} >true : true +const x5 = f +>x5 : boolean +>flet : boolean +>ff : { (): T; g(): U; } +>true : true + +let yy = 0; +>let : any +>yy : 0 +>0 : 0 + +const x6 = f +>x6 : boolean +>finterface : boolean +>ff : { (): T; g(): U; } +>true : true + +interface I {} +>interface : any +>I : any + +let x10 = f +>x10 : boolean +>fthis.bar() : boolean +>ff : { (): T; g(): U; } +>true : true + +this.bar() +>this.bar() : any +>this.bar : any +>this : typeof globalThis +>bar : any + +let x11 = f +>x11 : boolean +>ffunction bar() {} : boolean +>ff : { (): T; g(): U; } +>true : true + +function bar() {} +>function bar() {} : () => void +>bar : () => void + +let x12 = f +>x12 : boolean +>fclass C {} : boolean +>ff : { (): T; g(): U; } +>true : true + +class C {} +>class C {} : typeof C +>C : typeof C + +let x13 = f +>x13 : boolean +>fbar() : boolean +>ff : { (): T; g(): U; } +>true : true + +bar() +>bar() : any +>bar : any + +let x14 = f +>x14 : boolean +>fvoid bar() : boolean +>ff : { (): T; g(): U; } +>true : true + +void bar() +>void bar() : undefined +>bar() : any +>bar : any + +class C1 { +>C1 : C1 + + static specialFoo = f +>specialFoo : boolean +>f static : boolean +>ff : { (): T; g(): U; } +>string : any + + static bar = 123 +>static : any +>bar : number +>123 : 123 +} + +class C2 { +>C2 : C2 + + public specialFoo = f +>specialFoo : boolean +>f public : boolean +>ff : { (): T; g(): U; } +>string : any + + public bar = 123 +>public : any +>bar : number +>123 : 123 +} + +class C3 { +>C3 : C3 + + private specialFoo = f +>specialFoo : boolean +>f private : boolean +>ff : { (): T; g(): U; } +>string : any + + private bar = 123 +>private : any +>bar : number +>123 : 123 +} + +class C4 { +>C4 : C4 + + protected specialFoo = f +>specialFoo : boolean +>f protected : boolean +>ff : { (): T; g(): U; } +>string : any + + protected bar = 123 +>protected : any +>bar : number +>123 : 123 +} + +// Repro from #49551 + +const enum MyVer { v1 = 1, v2 = 2 } +>MyVer : MyVer +>v1 : MyVer.v1 +>1 : 1 +>v2 : MyVer.v2 +>2 : 2 + +let ver = 21 +>ver : number +>21 : 21 + +const a = ver < (MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2) +>a : boolean +>ver < (MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2) : boolean +>ver : number +>(MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2) : MyVer +>MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2 : MyVer +>MyVer.v1 >= MyVer.v2 : boolean +>MyVer.v1 : MyVer.v1 +>MyVer : typeof MyVer +>v1 : MyVer.v1 +>MyVer.v2 : MyVer.v2 +>MyVer : typeof MyVer +>v2 : MyVer.v2 +>MyVer.v1 : MyVer.v1 +>MyVer : typeof MyVer +>v1 : MyVer.v1 +>MyVer.v2 : MyVer.v2 +>MyVer : typeof MyVer +>v2 : MyVer.v2 + diff --git a/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts b/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts index 1a9377ae9c5c8..bd067a112342c 100644 --- a/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts +++ b/tests/cases/conformance/types/typeParameters/typeArgumentLists/instantiationExpressionErrors.ts @@ -47,3 +47,50 @@ true; const x4 = f if (true) {} + +const x5 = f +let yy = 0; + +const x6 = f +interface I {} + +let x10 = f +this.bar() + +let x11 = f +function bar() {} + +let x12 = f +class C {} + +let x13 = f +bar() + +let x14 = f +void bar() + +class C1 { + static specialFoo = f + static bar = 123 +} + +class C2 { + public specialFoo = f + public bar = 123 +} + +class C3 { + private specialFoo = f + private bar = 123 +} + +class C4 { + protected specialFoo = f + protected bar = 123 +} + +// Repro from #49551 + +const enum MyVer { v1 = 1, v2 = 2 } +let ver = 21 +const a = ver < (MyVer.v1 >= MyVer.v2 ? MyVer.v1 : MyVer.v2) From 76401adba33b71e70d76961d7d66064243be0243 Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Thu, 16 Jun 2022 17:59:56 +0000 Subject: [PATCH 3/3] Bump version to 4.7.4 and LKG --- lib/tsc.js | 5 ++- lib/tsserver.js | 83 ++++++++++++++++++++++++-------------- lib/tsserverlibrary.js | 83 ++++++++++++++++++++++++-------------- lib/typescript.js | 83 ++++++++++++++++++++++++-------------- lib/typescriptServices.js | 83 ++++++++++++++++++++++++-------------- lib/typingsInstaller.js | 5 ++- package.json | 2 +- src/compiler/corePublic.ts | 2 +- 8 files changed, 220 insertions(+), 126 deletions(-) diff --git a/lib/tsc.js b/lib/tsc.js index 7dd72bc6432c5..4964bb73e22c4 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -69,7 +69,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { var ts; (function (ts) { ts.versionMajorMinor = "4.7"; - ts.version = "4.7.3"; + ts.version = "4.7.4"; var NativeCollections; (function (NativeCollections) { var globals = typeof globalThis !== "undefined" ? globalThis : @@ -28447,9 +28447,10 @@ var ts; } nextToken(); var typeArguments = parseDelimitedList(20, parseType); - if (!parseExpected(31)) { + if (reScanGreaterToken() !== 31) { return undefined; } + nextToken(); return typeArguments && canFollowTypeArgumentsInExpression() ? typeArguments : undefined; } function canFollowTypeArgumentsInExpression() { diff --git a/lib/tsserver.js b/lib/tsserver.js index cccf548a539e8..c276781f379fd 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -100,7 +100,7 @@ var ts; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - ts.version = "4.7.3"; + ts.version = "4.7.4"; /* @internal */ var Comparison; (function (Comparison) { @@ -35424,10 +35424,11 @@ var ts; } nextToken(); var typeArguments = parseDelimitedList(20 /* ParsingContext.TypeArguments */, parseType); - if (!parseExpected(31 /* SyntaxKind.GreaterThanToken */)) { + if (reScanGreaterToken() !== 31 /* SyntaxKind.GreaterThanToken */) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + nextToken(); // We successfully parsed a type argument list. The next token determines whether we want to // treat it as such. If the type argument list is followed by `(` or a template literal, as in // `f(42)`, we favor the type argument interpretation even though JavaScript would view @@ -131465,10 +131466,9 @@ var ts; GlobalsSearch[GlobalsSearch["Success"] = 1] = "Success"; GlobalsSearch[GlobalsSearch["Fail"] = 2] = "Fail"; })(GlobalsSearch || (GlobalsSearch = {})); - function resolvingModuleSpecifiers(logPrefix, host, program, sourceFile, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { + function resolvingModuleSpecifiers(logPrefix, host, resolver, program, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { var _a, _b, _c; var start = ts.timestamp(); - var packageJsonImportFilter = ts.createPackageJsonImportFilter(sourceFile, preferences, host); // 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. @@ -131493,7 +131493,7 @@ var ts; return result; function tryResolve(exportInfo, symbolName, isFromAmbientModule) { if (isFromAmbientModule) { - var result_1 = ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences); + var result_1 = resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite); if (result_1) { ambientCount++; } @@ -131502,7 +131502,7 @@ var ts; var shouldResolveModuleSpecifier = needsFullResolution || preferences.allowIncompleteCompletions && resolvedCount < Completions.moduleSpecifierResolutionLimit; var shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier && preferences.allowIncompleteCompletions && cacheAttemptCount < Completions.moduleSpecifierResolutionCacheAttemptLimit; var result = (shouldResolveModuleSpecifier || shouldGetModuleSpecifierFromCache) - ? ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences, packageJsonImportFilter, shouldGetModuleSpecifierFromCache) + ? resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, shouldGetModuleSpecifierFromCache) : undefined; if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) { skippedAny = true; @@ -131607,7 +131607,7 @@ var ts; return undefined; var lowerCaseTokenText = location.text.toLowerCase(); var exportMap = ts.getExportInfoMap(file, host, program, cancellationToken); - var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, program, file, location.getStart(), preferences, + var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, ts.codefix.createImportSpecifierResolver(file, program, host, preferences), program, location.getStart(), preferences, /*isForImportStatementCompletion*/ false, ts.isValidTypeOnlyAliasUseSite(location), function (context) { var entries = ts.mapDefined(previousResponse.entries, function (entry) { var _a; @@ -132938,6 +132938,7 @@ var ts; var hasUnresolvedAutoImports = false; // This also gets mutated in nested-functions after the return var symbols = []; + var importSpecifierResolver; var symbolToOriginInfoMap = []; var symbolToSortTextMap = []; var seenPropertySymbols = new ts.Map(); @@ -133159,14 +133160,14 @@ var ts; } else { var fileName = ts.isExternalModuleNameRelative(ts.stripQuotes(moduleSymbol.name)) ? (_a = ts.getSourceFileOfModule(moduleSymbol)) === null || _a === void 0 ? void 0 : _a.fileName : undefined; - var moduleSpecifier = (ts.codefix.getModuleSpecifierForBestExportInfo([{ + var moduleSpecifier = ((importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences))).getModuleSpecifierForBestExportInfo([{ exportKind: 0 /* ExportKind.Named */, moduleFileName: fileName, isFromPackageJson: false, moduleSymbol: moduleSymbol, symbol: firstAccessibleSymbol, targetFlags: ts.skipAlias(firstAccessibleSymbol, typeChecker).flags, - }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location), sourceFile, program, host, preferences) || {}).moduleSpecifier; + }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location)) || {}).moduleSpecifier; if (moduleSpecifier) { var origin = { kind: getNullableSymbolOriginInfoKind(6 /* SymbolOriginInfoKind.SymbolMemberExport */), @@ -133422,7 +133423,7 @@ var ts; var exportInfo = ts.getExportInfoMap(sourceFile, host, program, cancellationToken); var packageJsonAutoImportProvider = (_b = host.getPackageJsonAutoImportProvider) === null || _b === void 0 ? void 0 : _b.call(host); var packageJsonFilter = detailsEntryId ? undefined : ts.createPackageJsonImportFilter(sourceFile, preferences, host); - resolvingModuleSpecifiers("collectAutoImports", host, program, sourceFile, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { + resolvingModuleSpecifiers("collectAutoImports", host, importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)), program, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { exportInfo.search(sourceFile.path, /*preferCapitalized*/ isRightOfOpenTag, function (symbolName, targetFlags) { if (!ts.isIdentifierText(symbolName, ts.getEmitScriptTarget(host.getCompilationSettings()))) @@ -152453,6 +152454,18 @@ var ts; return addToNamespace.length > 0 || importType.length > 0 || addToExisting.size > 0 || newImports.size > 0; } } + function createImportSpecifierResolver(importingFile, program, host, preferences) { + var packageJsonImportFilter = ts.createPackageJsonImportFilter(importingFile, preferences, host); + var importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); + return { getModuleSpecifierForBestExportInfo: getModuleSpecifierForBestExportInfo }; + function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, fromCacheOnly) { + var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, + /*useRequire*/ false, program, importingFile, host, preferences, importMap, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; + var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter, host); + return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); + } + } + codefix.createImportSpecifierResolver = createImportSpecifierResolver; // Sorted with the preferred fix coming first. var ImportFixKind; (function (ImportFixKind) { @@ -152553,18 +152566,12 @@ var ts; return !moduleFile || ts.isImportableFile(program, importingFile, moduleFile, preferences, /*packageJsonFilter*/ undefined, getModuleSpecifierResolutionHost(isFromPackageJson), (_a = host.getModuleSpecifierCache) === null || _a === void 0 ? void 0 : _a.call(host)); } } - function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, importingFile, program, host, preferences, packageJsonImportFilter, fromCacheOnly) { - var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, - /*useRequire*/ false, program, importingFile, host, preferences, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; - var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter || ts.createPackageJsonImportFilter(importingFile, preferences, host), host); - return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); - } - codefix.getModuleSpecifierForBestExportInfo = getModuleSpecifierForBestExportInfo; function getImportFixes(exportInfos, useNamespaceInfo, /** undefined only for missing JSX namespace */ - isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, fromCacheOnly) { + isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, importMap, fromCacheOnly) { + if (importMap === void 0) { importMap = createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()); } var checker = program.getTypeChecker(); - var existingImports = ts.flatMap(exportInfos, function (info) { return getExistingImportDeclarations(info, checker, sourceFile, program.getCompilerOptions()); }); + var existingImports = ts.flatMap(exportInfos, importMap.getImportsForExportInfo); var useNamespace = useNamespaceInfo && tryUseExistingNamespaceImport(existingImports, useNamespaceInfo.symbolName, useNamespaceInfo.position, checker); var addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions()); if (addToExisting) { @@ -152692,21 +152699,37 @@ var ts; }; }); } - function getExistingImportDeclarations(_a, checker, importingFile, compilerOptions) { - var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; - // Can't use an es6 import for a type in JS. - if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) - return ts.emptyArray; - var importKind = getImportKind(importingFile, exportKind, compilerOptions); - return ts.mapDefined(importingFile.imports, function (moduleSpecifier) { + function createExistingImportMap(checker, importingFile, compilerOptions) { + var importMap; + for (var _i = 0, _a = importingFile.imports; _i < _a.length; _i++) { + var moduleSpecifier = _a[_i]; var i = ts.importFromModuleSpecifier(moduleSpecifier); if (ts.isVariableDeclarationInitializedToRequire(i.parent)) { - return checker.resolveExternalModuleName(moduleSpecifier) === moduleSymbol ? { declaration: i.parent, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + var moduleSymbol = checker.resolveExternalModuleName(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i.parent); + } } - if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { - return checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + else if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { + var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i); + } } - }); + } + return { + getImportsForExportInfo: function (_a) { + var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; + // Can't use an es6 import for a type in JS. + if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) + return ts.emptyArray; + var matchingDeclarations = importMap === null || importMap === void 0 ? void 0 : importMap.get(ts.getSymbolId(moduleSymbol)); + if (!matchingDeclarations) + return ts.emptyArray; + var importKind = getImportKind(importingFile, exportKind, compilerOptions); + return matchingDeclarations.map(function (declaration) { return ({ declaration: declaration, importKind: importKind, symbol: symbol, targetFlags: targetFlags }); }); + } + }; } function shouldUseRequire(sourceFile, program) { // 1. TypeScript files don't use require variable declarations diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index a32ed4a819d26..5972181ff345c 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -294,7 +294,7 @@ var ts; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - ts.version = "4.7.3"; + ts.version = "4.7.4"; /* @internal */ var Comparison; (function (Comparison) { @@ -35618,10 +35618,11 @@ var ts; } nextToken(); var typeArguments = parseDelimitedList(20 /* ParsingContext.TypeArguments */, parseType); - if (!parseExpected(31 /* SyntaxKind.GreaterThanToken */)) { + if (reScanGreaterToken() !== 31 /* SyntaxKind.GreaterThanToken */) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + nextToken(); // We successfully parsed a type argument list. The next token determines whether we want to // treat it as such. If the type argument list is followed by `(` or a template literal, as in // `f(42)`, we favor the type argument interpretation even though JavaScript would view @@ -132076,10 +132077,9 @@ var ts; GlobalsSearch[GlobalsSearch["Success"] = 1] = "Success"; GlobalsSearch[GlobalsSearch["Fail"] = 2] = "Fail"; })(GlobalsSearch || (GlobalsSearch = {})); - function resolvingModuleSpecifiers(logPrefix, host, program, sourceFile, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { + function resolvingModuleSpecifiers(logPrefix, host, resolver, program, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { var _a, _b, _c; var start = ts.timestamp(); - var packageJsonImportFilter = ts.createPackageJsonImportFilter(sourceFile, preferences, host); // 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. @@ -132104,7 +132104,7 @@ var ts; return result; function tryResolve(exportInfo, symbolName, isFromAmbientModule) { if (isFromAmbientModule) { - var result_1 = ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences); + var result_1 = resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite); if (result_1) { ambientCount++; } @@ -132113,7 +132113,7 @@ var ts; var shouldResolveModuleSpecifier = needsFullResolution || preferences.allowIncompleteCompletions && resolvedCount < Completions.moduleSpecifierResolutionLimit; var shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier && preferences.allowIncompleteCompletions && cacheAttemptCount < Completions.moduleSpecifierResolutionCacheAttemptLimit; var result = (shouldResolveModuleSpecifier || shouldGetModuleSpecifierFromCache) - ? ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences, packageJsonImportFilter, shouldGetModuleSpecifierFromCache) + ? resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, shouldGetModuleSpecifierFromCache) : undefined; if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) { skippedAny = true; @@ -132218,7 +132218,7 @@ var ts; return undefined; var lowerCaseTokenText = location.text.toLowerCase(); var exportMap = ts.getExportInfoMap(file, host, program, cancellationToken); - var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, program, file, location.getStart(), preferences, + var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, ts.codefix.createImportSpecifierResolver(file, program, host, preferences), program, location.getStart(), preferences, /*isForImportStatementCompletion*/ false, ts.isValidTypeOnlyAliasUseSite(location), function (context) { var entries = ts.mapDefined(previousResponse.entries, function (entry) { var _a; @@ -133549,6 +133549,7 @@ var ts; var hasUnresolvedAutoImports = false; // This also gets mutated in nested-functions after the return var symbols = []; + var importSpecifierResolver; var symbolToOriginInfoMap = []; var symbolToSortTextMap = []; var seenPropertySymbols = new ts.Map(); @@ -133770,14 +133771,14 @@ var ts; } else { var fileName = ts.isExternalModuleNameRelative(ts.stripQuotes(moduleSymbol.name)) ? (_a = ts.getSourceFileOfModule(moduleSymbol)) === null || _a === void 0 ? void 0 : _a.fileName : undefined; - var moduleSpecifier = (ts.codefix.getModuleSpecifierForBestExportInfo([{ + var moduleSpecifier = ((importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences))).getModuleSpecifierForBestExportInfo([{ exportKind: 0 /* ExportKind.Named */, moduleFileName: fileName, isFromPackageJson: false, moduleSymbol: moduleSymbol, symbol: firstAccessibleSymbol, targetFlags: ts.skipAlias(firstAccessibleSymbol, typeChecker).flags, - }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location), sourceFile, program, host, preferences) || {}).moduleSpecifier; + }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location)) || {}).moduleSpecifier; if (moduleSpecifier) { var origin = { kind: getNullableSymbolOriginInfoKind(6 /* SymbolOriginInfoKind.SymbolMemberExport */), @@ -134033,7 +134034,7 @@ var ts; var exportInfo = ts.getExportInfoMap(sourceFile, host, program, cancellationToken); var packageJsonAutoImportProvider = (_b = host.getPackageJsonAutoImportProvider) === null || _b === void 0 ? void 0 : _b.call(host); var packageJsonFilter = detailsEntryId ? undefined : ts.createPackageJsonImportFilter(sourceFile, preferences, host); - resolvingModuleSpecifiers("collectAutoImports", host, program, sourceFile, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { + resolvingModuleSpecifiers("collectAutoImports", host, importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)), program, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { exportInfo.search(sourceFile.path, /*preferCapitalized*/ isRightOfOpenTag, function (symbolName, targetFlags) { if (!ts.isIdentifierText(symbolName, ts.getEmitScriptTarget(host.getCompilationSettings()))) @@ -153064,6 +153065,18 @@ var ts; return addToNamespace.length > 0 || importType.length > 0 || addToExisting.size > 0 || newImports.size > 0; } } + function createImportSpecifierResolver(importingFile, program, host, preferences) { + var packageJsonImportFilter = ts.createPackageJsonImportFilter(importingFile, preferences, host); + var importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); + return { getModuleSpecifierForBestExportInfo: getModuleSpecifierForBestExportInfo }; + function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, fromCacheOnly) { + var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, + /*useRequire*/ false, program, importingFile, host, preferences, importMap, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; + var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter, host); + return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); + } + } + codefix.createImportSpecifierResolver = createImportSpecifierResolver; // Sorted with the preferred fix coming first. var ImportFixKind; (function (ImportFixKind) { @@ -153164,18 +153177,12 @@ var ts; return !moduleFile || ts.isImportableFile(program, importingFile, moduleFile, preferences, /*packageJsonFilter*/ undefined, getModuleSpecifierResolutionHost(isFromPackageJson), (_a = host.getModuleSpecifierCache) === null || _a === void 0 ? void 0 : _a.call(host)); } } - function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, importingFile, program, host, preferences, packageJsonImportFilter, fromCacheOnly) { - var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, - /*useRequire*/ false, program, importingFile, host, preferences, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; - var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter || ts.createPackageJsonImportFilter(importingFile, preferences, host), host); - return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); - } - codefix.getModuleSpecifierForBestExportInfo = getModuleSpecifierForBestExportInfo; function getImportFixes(exportInfos, useNamespaceInfo, /** undefined only for missing JSX namespace */ - isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, fromCacheOnly) { + isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, importMap, fromCacheOnly) { + if (importMap === void 0) { importMap = createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()); } var checker = program.getTypeChecker(); - var existingImports = ts.flatMap(exportInfos, function (info) { return getExistingImportDeclarations(info, checker, sourceFile, program.getCompilerOptions()); }); + var existingImports = ts.flatMap(exportInfos, importMap.getImportsForExportInfo); var useNamespace = useNamespaceInfo && tryUseExistingNamespaceImport(existingImports, useNamespaceInfo.symbolName, useNamespaceInfo.position, checker); var addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions()); if (addToExisting) { @@ -153303,21 +153310,37 @@ var ts; }; }); } - function getExistingImportDeclarations(_a, checker, importingFile, compilerOptions) { - var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; - // Can't use an es6 import for a type in JS. - if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) - return ts.emptyArray; - var importKind = getImportKind(importingFile, exportKind, compilerOptions); - return ts.mapDefined(importingFile.imports, function (moduleSpecifier) { + function createExistingImportMap(checker, importingFile, compilerOptions) { + var importMap; + for (var _i = 0, _a = importingFile.imports; _i < _a.length; _i++) { + var moduleSpecifier = _a[_i]; var i = ts.importFromModuleSpecifier(moduleSpecifier); if (ts.isVariableDeclarationInitializedToRequire(i.parent)) { - return checker.resolveExternalModuleName(moduleSpecifier) === moduleSymbol ? { declaration: i.parent, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + var moduleSymbol = checker.resolveExternalModuleName(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i.parent); + } } - if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { - return checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + else if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { + var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i); + } } - }); + } + return { + getImportsForExportInfo: function (_a) { + var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; + // Can't use an es6 import for a type in JS. + if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) + return ts.emptyArray; + var matchingDeclarations = importMap === null || importMap === void 0 ? void 0 : importMap.get(ts.getSymbolId(moduleSymbol)); + if (!matchingDeclarations) + return ts.emptyArray; + var importKind = getImportKind(importingFile, exportKind, compilerOptions); + return matchingDeclarations.map(function (declaration) { return ({ declaration: declaration, importKind: importKind, symbol: symbol, targetFlags: targetFlags }); }); + } + }; } function shouldUseRequire(sourceFile, program) { // 1. TypeScript files don't use require variable declarations diff --git a/lib/typescript.js b/lib/typescript.js index 67c644c042c7d..e8734a648d0bc 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -294,7 +294,7 @@ var ts; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - ts.version = "4.7.3"; + ts.version = "4.7.4"; /* @internal */ var Comparison; (function (Comparison) { @@ -35618,10 +35618,11 @@ var ts; } nextToken(); var typeArguments = parseDelimitedList(20 /* ParsingContext.TypeArguments */, parseType); - if (!parseExpected(31 /* SyntaxKind.GreaterThanToken */)) { + if (reScanGreaterToken() !== 31 /* SyntaxKind.GreaterThanToken */) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + nextToken(); // We successfully parsed a type argument list. The next token determines whether we want to // treat it as such. If the type argument list is followed by `(` or a template literal, as in // `f(42)`, we favor the type argument interpretation even though JavaScript would view @@ -132076,10 +132077,9 @@ var ts; GlobalsSearch[GlobalsSearch["Success"] = 1] = "Success"; GlobalsSearch[GlobalsSearch["Fail"] = 2] = "Fail"; })(GlobalsSearch || (GlobalsSearch = {})); - function resolvingModuleSpecifiers(logPrefix, host, program, sourceFile, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { + function resolvingModuleSpecifiers(logPrefix, host, resolver, program, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { var _a, _b, _c; var start = ts.timestamp(); - var packageJsonImportFilter = ts.createPackageJsonImportFilter(sourceFile, preferences, host); // 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. @@ -132104,7 +132104,7 @@ var ts; return result; function tryResolve(exportInfo, symbolName, isFromAmbientModule) { if (isFromAmbientModule) { - var result_1 = ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences); + var result_1 = resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite); if (result_1) { ambientCount++; } @@ -132113,7 +132113,7 @@ var ts; var shouldResolveModuleSpecifier = needsFullResolution || preferences.allowIncompleteCompletions && resolvedCount < Completions.moduleSpecifierResolutionLimit; var shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier && preferences.allowIncompleteCompletions && cacheAttemptCount < Completions.moduleSpecifierResolutionCacheAttemptLimit; var result = (shouldResolveModuleSpecifier || shouldGetModuleSpecifierFromCache) - ? ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences, packageJsonImportFilter, shouldGetModuleSpecifierFromCache) + ? resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, shouldGetModuleSpecifierFromCache) : undefined; if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) { skippedAny = true; @@ -132218,7 +132218,7 @@ var ts; return undefined; var lowerCaseTokenText = location.text.toLowerCase(); var exportMap = ts.getExportInfoMap(file, host, program, cancellationToken); - var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, program, file, location.getStart(), preferences, + var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, ts.codefix.createImportSpecifierResolver(file, program, host, preferences), program, location.getStart(), preferences, /*isForImportStatementCompletion*/ false, ts.isValidTypeOnlyAliasUseSite(location), function (context) { var entries = ts.mapDefined(previousResponse.entries, function (entry) { var _a; @@ -133549,6 +133549,7 @@ var ts; var hasUnresolvedAutoImports = false; // This also gets mutated in nested-functions after the return var symbols = []; + var importSpecifierResolver; var symbolToOriginInfoMap = []; var symbolToSortTextMap = []; var seenPropertySymbols = new ts.Map(); @@ -133770,14 +133771,14 @@ var ts; } else { var fileName = ts.isExternalModuleNameRelative(ts.stripQuotes(moduleSymbol.name)) ? (_a = ts.getSourceFileOfModule(moduleSymbol)) === null || _a === void 0 ? void 0 : _a.fileName : undefined; - var moduleSpecifier = (ts.codefix.getModuleSpecifierForBestExportInfo([{ + var moduleSpecifier = ((importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences))).getModuleSpecifierForBestExportInfo([{ exportKind: 0 /* ExportKind.Named */, moduleFileName: fileName, isFromPackageJson: false, moduleSymbol: moduleSymbol, symbol: firstAccessibleSymbol, targetFlags: ts.skipAlias(firstAccessibleSymbol, typeChecker).flags, - }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location), sourceFile, program, host, preferences) || {}).moduleSpecifier; + }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location)) || {}).moduleSpecifier; if (moduleSpecifier) { var origin = { kind: getNullableSymbolOriginInfoKind(6 /* SymbolOriginInfoKind.SymbolMemberExport */), @@ -134033,7 +134034,7 @@ var ts; var exportInfo = ts.getExportInfoMap(sourceFile, host, program, cancellationToken); var packageJsonAutoImportProvider = (_b = host.getPackageJsonAutoImportProvider) === null || _b === void 0 ? void 0 : _b.call(host); var packageJsonFilter = detailsEntryId ? undefined : ts.createPackageJsonImportFilter(sourceFile, preferences, host); - resolvingModuleSpecifiers("collectAutoImports", host, program, sourceFile, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { + resolvingModuleSpecifiers("collectAutoImports", host, importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)), program, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { exportInfo.search(sourceFile.path, /*preferCapitalized*/ isRightOfOpenTag, function (symbolName, targetFlags) { if (!ts.isIdentifierText(symbolName, ts.getEmitScriptTarget(host.getCompilationSettings()))) @@ -153064,6 +153065,18 @@ var ts; return addToNamespace.length > 0 || importType.length > 0 || addToExisting.size > 0 || newImports.size > 0; } } + function createImportSpecifierResolver(importingFile, program, host, preferences) { + var packageJsonImportFilter = ts.createPackageJsonImportFilter(importingFile, preferences, host); + var importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); + return { getModuleSpecifierForBestExportInfo: getModuleSpecifierForBestExportInfo }; + function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, fromCacheOnly) { + var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, + /*useRequire*/ false, program, importingFile, host, preferences, importMap, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; + var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter, host); + return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); + } + } + codefix.createImportSpecifierResolver = createImportSpecifierResolver; // Sorted with the preferred fix coming first. var ImportFixKind; (function (ImportFixKind) { @@ -153164,18 +153177,12 @@ var ts; return !moduleFile || ts.isImportableFile(program, importingFile, moduleFile, preferences, /*packageJsonFilter*/ undefined, getModuleSpecifierResolutionHost(isFromPackageJson), (_a = host.getModuleSpecifierCache) === null || _a === void 0 ? void 0 : _a.call(host)); } } - function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, importingFile, program, host, preferences, packageJsonImportFilter, fromCacheOnly) { - var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, - /*useRequire*/ false, program, importingFile, host, preferences, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; - var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter || ts.createPackageJsonImportFilter(importingFile, preferences, host), host); - return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); - } - codefix.getModuleSpecifierForBestExportInfo = getModuleSpecifierForBestExportInfo; function getImportFixes(exportInfos, useNamespaceInfo, /** undefined only for missing JSX namespace */ - isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, fromCacheOnly) { + isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, importMap, fromCacheOnly) { + if (importMap === void 0) { importMap = createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()); } var checker = program.getTypeChecker(); - var existingImports = ts.flatMap(exportInfos, function (info) { return getExistingImportDeclarations(info, checker, sourceFile, program.getCompilerOptions()); }); + var existingImports = ts.flatMap(exportInfos, importMap.getImportsForExportInfo); var useNamespace = useNamespaceInfo && tryUseExistingNamespaceImport(existingImports, useNamespaceInfo.symbolName, useNamespaceInfo.position, checker); var addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions()); if (addToExisting) { @@ -153303,21 +153310,37 @@ var ts; }; }); } - function getExistingImportDeclarations(_a, checker, importingFile, compilerOptions) { - var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; - // Can't use an es6 import for a type in JS. - if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) - return ts.emptyArray; - var importKind = getImportKind(importingFile, exportKind, compilerOptions); - return ts.mapDefined(importingFile.imports, function (moduleSpecifier) { + function createExistingImportMap(checker, importingFile, compilerOptions) { + var importMap; + for (var _i = 0, _a = importingFile.imports; _i < _a.length; _i++) { + var moduleSpecifier = _a[_i]; var i = ts.importFromModuleSpecifier(moduleSpecifier); if (ts.isVariableDeclarationInitializedToRequire(i.parent)) { - return checker.resolveExternalModuleName(moduleSpecifier) === moduleSymbol ? { declaration: i.parent, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + var moduleSymbol = checker.resolveExternalModuleName(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i.parent); + } } - if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { - return checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + else if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { + var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i); + } } - }); + } + return { + getImportsForExportInfo: function (_a) { + var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; + // Can't use an es6 import for a type in JS. + if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) + return ts.emptyArray; + var matchingDeclarations = importMap === null || importMap === void 0 ? void 0 : importMap.get(ts.getSymbolId(moduleSymbol)); + if (!matchingDeclarations) + return ts.emptyArray; + var importKind = getImportKind(importingFile, exportKind, compilerOptions); + return matchingDeclarations.map(function (declaration) { return ({ declaration: declaration, importKind: importKind, symbol: symbol, targetFlags: targetFlags }); }); + } + }; } function shouldUseRequire(sourceFile, program) { // 1. TypeScript files don't use require variable declarations diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index b29e783239371..4e94b0f252400 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -294,7 +294,7 @@ var ts; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - ts.version = "4.7.3"; + ts.version = "4.7.4"; /* @internal */ var Comparison; (function (Comparison) { @@ -35618,10 +35618,11 @@ var ts; } nextToken(); var typeArguments = parseDelimitedList(20 /* ParsingContext.TypeArguments */, parseType); - if (!parseExpected(31 /* SyntaxKind.GreaterThanToken */)) { + if (reScanGreaterToken() !== 31 /* SyntaxKind.GreaterThanToken */) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + nextToken(); // We successfully parsed a type argument list. The next token determines whether we want to // treat it as such. If the type argument list is followed by `(` or a template literal, as in // `f(42)`, we favor the type argument interpretation even though JavaScript would view @@ -132076,10 +132077,9 @@ var ts; GlobalsSearch[GlobalsSearch["Success"] = 1] = "Success"; GlobalsSearch[GlobalsSearch["Fail"] = 2] = "Fail"; })(GlobalsSearch || (GlobalsSearch = {})); - function resolvingModuleSpecifiers(logPrefix, host, program, sourceFile, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { + function resolvingModuleSpecifiers(logPrefix, host, resolver, program, position, preferences, isForImportStatementCompletion, isValidTypeOnlyUseSite, cb) { var _a, _b, _c; var start = ts.timestamp(); - var packageJsonImportFilter = ts.createPackageJsonImportFilter(sourceFile, preferences, host); // 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. @@ -132104,7 +132104,7 @@ var ts; return result; function tryResolve(exportInfo, symbolName, isFromAmbientModule) { if (isFromAmbientModule) { - var result_1 = ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences); + var result_1 = resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite); if (result_1) { ambientCount++; } @@ -132113,7 +132113,7 @@ var ts; var shouldResolveModuleSpecifier = needsFullResolution || preferences.allowIncompleteCompletions && resolvedCount < Completions.moduleSpecifierResolutionLimit; var shouldGetModuleSpecifierFromCache = !shouldResolveModuleSpecifier && preferences.allowIncompleteCompletions && cacheAttemptCount < Completions.moduleSpecifierResolutionCacheAttemptLimit; var result = (shouldResolveModuleSpecifier || shouldGetModuleSpecifierFromCache) - ? ts.codefix.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, sourceFile, program, host, preferences, packageJsonImportFilter, shouldGetModuleSpecifierFromCache) + ? resolver.getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, shouldGetModuleSpecifierFromCache) : undefined; if (!shouldResolveModuleSpecifier && !shouldGetModuleSpecifierFromCache || shouldGetModuleSpecifierFromCache && !result) { skippedAny = true; @@ -132218,7 +132218,7 @@ var ts; return undefined; var lowerCaseTokenText = location.text.toLowerCase(); var exportMap = ts.getExportInfoMap(file, host, program, cancellationToken); - var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, program, file, location.getStart(), preferences, + var newEntries = resolvingModuleSpecifiers("continuePreviousIncompleteResponse", host, ts.codefix.createImportSpecifierResolver(file, program, host, preferences), program, location.getStart(), preferences, /*isForImportStatementCompletion*/ false, ts.isValidTypeOnlyAliasUseSite(location), function (context) { var entries = ts.mapDefined(previousResponse.entries, function (entry) { var _a; @@ -133549,6 +133549,7 @@ var ts; var hasUnresolvedAutoImports = false; // This also gets mutated in nested-functions after the return var symbols = []; + var importSpecifierResolver; var symbolToOriginInfoMap = []; var symbolToSortTextMap = []; var seenPropertySymbols = new ts.Map(); @@ -133770,14 +133771,14 @@ var ts; } else { var fileName = ts.isExternalModuleNameRelative(ts.stripQuotes(moduleSymbol.name)) ? (_a = ts.getSourceFileOfModule(moduleSymbol)) === null || _a === void 0 ? void 0 : _a.fileName : undefined; - var moduleSpecifier = (ts.codefix.getModuleSpecifierForBestExportInfo([{ + var moduleSpecifier = ((importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences))).getModuleSpecifierForBestExportInfo([{ exportKind: 0 /* ExportKind.Named */, moduleFileName: fileName, isFromPackageJson: false, moduleSymbol: moduleSymbol, symbol: firstAccessibleSymbol, targetFlags: ts.skipAlias(firstAccessibleSymbol, typeChecker).flags, - }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location), sourceFile, program, host, preferences) || {}).moduleSpecifier; + }], firstAccessibleSymbol.name, position, ts.isValidTypeOnlyAliasUseSite(location)) || {}).moduleSpecifier; if (moduleSpecifier) { var origin = { kind: getNullableSymbolOriginInfoKind(6 /* SymbolOriginInfoKind.SymbolMemberExport */), @@ -134033,7 +134034,7 @@ var ts; var exportInfo = ts.getExportInfoMap(sourceFile, host, program, cancellationToken); var packageJsonAutoImportProvider = (_b = host.getPackageJsonAutoImportProvider) === null || _b === void 0 ? void 0 : _b.call(host); var packageJsonFilter = detailsEntryId ? undefined : ts.createPackageJsonImportFilter(sourceFile, preferences, host); - resolvingModuleSpecifiers("collectAutoImports", host, program, sourceFile, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { + resolvingModuleSpecifiers("collectAutoImports", host, importSpecifierResolver || (importSpecifierResolver = ts.codefix.createImportSpecifierResolver(sourceFile, program, host, preferences)), program, position, preferences, !!importCompletionNode, ts.isValidTypeOnlyAliasUseSite(location), function (context) { exportInfo.search(sourceFile.path, /*preferCapitalized*/ isRightOfOpenTag, function (symbolName, targetFlags) { if (!ts.isIdentifierText(symbolName, ts.getEmitScriptTarget(host.getCompilationSettings()))) @@ -153064,6 +153065,18 @@ var ts; return addToNamespace.length > 0 || importType.length > 0 || addToExisting.size > 0 || newImports.size > 0; } } + function createImportSpecifierResolver(importingFile, program, host, preferences) { + var packageJsonImportFilter = ts.createPackageJsonImportFilter(importingFile, preferences, host); + var importMap = createExistingImportMap(program.getTypeChecker(), importingFile, program.getCompilerOptions()); + return { getModuleSpecifierForBestExportInfo: getModuleSpecifierForBestExportInfo }; + function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, fromCacheOnly) { + var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, + /*useRequire*/ false, program, importingFile, host, preferences, importMap, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; + var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter, host); + return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); + } + } + codefix.createImportSpecifierResolver = createImportSpecifierResolver; // Sorted with the preferred fix coming first. var ImportFixKind; (function (ImportFixKind) { @@ -153164,18 +153177,12 @@ var ts; return !moduleFile || ts.isImportableFile(program, importingFile, moduleFile, preferences, /*packageJsonFilter*/ undefined, getModuleSpecifierResolutionHost(isFromPackageJson), (_a = host.getModuleSpecifierCache) === null || _a === void 0 ? void 0 : _a.call(host)); } } - function getModuleSpecifierForBestExportInfo(exportInfo, symbolName, position, isValidTypeOnlyUseSite, importingFile, program, host, preferences, packageJsonImportFilter, fromCacheOnly) { - var _a = getImportFixes(exportInfo, { symbolName: symbolName, position: position }, isValidTypeOnlyUseSite, - /*useRequire*/ false, program, importingFile, host, preferences, fromCacheOnly), fixes = _a.fixes, computedWithoutCacheCount = _a.computedWithoutCacheCount; - var result = getBestFix(fixes, importingFile, program, packageJsonImportFilter || ts.createPackageJsonImportFilter(importingFile, preferences, host), host); - return result && __assign(__assign({}, result), { computedWithoutCacheCount: computedWithoutCacheCount }); - } - codefix.getModuleSpecifierForBestExportInfo = getModuleSpecifierForBestExportInfo; function getImportFixes(exportInfos, useNamespaceInfo, /** undefined only for missing JSX namespace */ - isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, fromCacheOnly) { + isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences, importMap, fromCacheOnly) { + if (importMap === void 0) { importMap = createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()); } var checker = program.getTypeChecker(); - var existingImports = ts.flatMap(exportInfos, function (info) { return getExistingImportDeclarations(info, checker, sourceFile, program.getCompilerOptions()); }); + var existingImports = ts.flatMap(exportInfos, importMap.getImportsForExportInfo); var useNamespace = useNamespaceInfo && tryUseExistingNamespaceImport(existingImports, useNamespaceInfo.symbolName, useNamespaceInfo.position, checker); var addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions()); if (addToExisting) { @@ -153303,21 +153310,37 @@ var ts; }; }); } - function getExistingImportDeclarations(_a, checker, importingFile, compilerOptions) { - var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; - // Can't use an es6 import for a type in JS. - if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) - return ts.emptyArray; - var importKind = getImportKind(importingFile, exportKind, compilerOptions); - return ts.mapDefined(importingFile.imports, function (moduleSpecifier) { + function createExistingImportMap(checker, importingFile, compilerOptions) { + var importMap; + for (var _i = 0, _a = importingFile.imports; _i < _a.length; _i++) { + var moduleSpecifier = _a[_i]; var i = ts.importFromModuleSpecifier(moduleSpecifier); if (ts.isVariableDeclarationInitializedToRequire(i.parent)) { - return checker.resolveExternalModuleName(moduleSpecifier) === moduleSymbol ? { declaration: i.parent, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + var moduleSymbol = checker.resolveExternalModuleName(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i.parent); + } } - if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { - return checker.getSymbolAtLocation(moduleSpecifier) === moduleSymbol ? { declaration: i, importKind: importKind, symbol: symbol, targetFlags: targetFlags } : undefined; + else if (i.kind === 266 /* SyntaxKind.ImportDeclaration */ || i.kind === 265 /* SyntaxKind.ImportEqualsDeclaration */) { + var moduleSymbol = checker.getSymbolAtLocation(moduleSpecifier); + if (moduleSymbol) { + (importMap || (importMap = ts.createMultiMap())).add(ts.getSymbolId(moduleSymbol), i); + } } - }); + } + return { + getImportsForExportInfo: function (_a) { + var moduleSymbol = _a.moduleSymbol, exportKind = _a.exportKind, targetFlags = _a.targetFlags, symbol = _a.symbol; + // Can't use an es6 import for a type in JS. + if (!(targetFlags & 111551 /* SymbolFlags.Value */) && ts.isSourceFileJS(importingFile)) + return ts.emptyArray; + var matchingDeclarations = importMap === null || importMap === void 0 ? void 0 : importMap.get(ts.getSymbolId(moduleSymbol)); + if (!matchingDeclarations) + return ts.emptyArray; + var importKind = getImportKind(importingFile, exportKind, compilerOptions); + return matchingDeclarations.map(function (declaration) { return ({ declaration: declaration, importKind: importKind, symbol: symbol, targetFlags: targetFlags }); }); + } + }; } function shouldUseRequire(sourceFile, program) { // 1. TypeScript files don't use require variable declarations diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 05870bdae2a13..83d1ad5de4924 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -89,7 +89,7 @@ var ts; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - ts.version = "4.7.3"; + ts.version = "4.7.4"; /* @internal */ var Comparison; (function (Comparison) { @@ -35413,10 +35413,11 @@ var ts; } nextToken(); var typeArguments = parseDelimitedList(20 /* ParsingContext.TypeArguments */, parseType); - if (!parseExpected(31 /* SyntaxKind.GreaterThanToken */)) { + if (reScanGreaterToken() !== 31 /* SyntaxKind.GreaterThanToken */) { // If it doesn't have the closing `>` then it's definitely not an type argument list. return undefined; } + nextToken(); // We successfully parsed a type argument list. The next token determines whether we want to // treat it as such. If the type argument list is followed by `(` or a template literal, as in // `f(42)`, we favor the type argument interpretation even though JavaScript would view diff --git a/package.json b/package.json index 9723e5d2e7ac3..bcf533747d0a8 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "4.7.3", + "version": "4.7.4", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index 6678bc8204c2b..ede2756aaad7d 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -5,7 +5,7 @@ namespace ts { // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - export const version = "4.7.3" as string; + export const version = "4.7.4" as string; /** * Type of objects whose values are all of the same type.