1/* @internal */ 2namespace ts.codefix { 3 const fixName = "fixCannotFindModule"; 4 const fixIdInstallTypesPackage = "installTypesPackage"; 5 6 const errorCodeCannotFindModule = Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations.code; 7 const errorCodes = [ 8 errorCodeCannotFindModule, 9 Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type.code, 10 ]; 11 registerCodeFix({ 12 errorCodes, 13 getCodeActions: context => { 14 const { host, sourceFile, span: { start } } = context; 15 const packageName = tryGetImportedPackageName(sourceFile, start); 16 if (packageName === undefined) return undefined; 17 const typesPackageName = getTypesPackageNameToInstall(packageName, host, context.errorCode); 18 return typesPackageName === undefined 19 ? [] 20 : [createCodeFixAction(fixName, /*changes*/ [], [Diagnostics.Install_0, typesPackageName], fixIdInstallTypesPackage, Diagnostics.Install_all_missing_types_packages, getInstallCommand(sourceFile.fileName, typesPackageName))]; 21 }, 22 fixIds: [fixIdInstallTypesPackage], 23 getAllCodeActions: context => { 24 return codeFixAll(context, errorCodes, (_changes, diag, commands) => { 25 const packageName = tryGetImportedPackageName(diag.file, diag.start); 26 if (packageName === undefined) return undefined; 27 switch (context.fixId) { 28 case fixIdInstallTypesPackage: { 29 const pkg = getTypesPackageNameToInstall(packageName, context.host, diag.code); 30 if (pkg) { 31 commands.push(getInstallCommand(diag.file.fileName, pkg)); 32 } 33 break; 34 } 35 default: 36 Debug.fail(`Bad fixId: ${context.fixId}`); 37 } 38 }); 39 }, 40 }); 41 42 function getInstallCommand(fileName: string, packageName: string): InstallPackageAction { 43 return { type: "install package", file: fileName, packageName }; 44 } 45 46 function tryGetImportedPackageName(sourceFile: SourceFile, pos: number): string | undefined { 47 const moduleName = cast(getTokenAtPosition(sourceFile, pos), isStringLiteral).text; 48 const { packageName } = parsePackageName(moduleName); 49 return isExternalModuleNameRelative(packageName) ? undefined : packageName; 50 } 51 52 function getTypesPackageNameToInstall(packageName: string, host: LanguageServiceHost, diagCode: number): string | undefined { 53 return diagCode === errorCodeCannotFindModule 54 ? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) 55 : (host.isKnownTypesPackageName?.(packageName) ? getTypesPackageName(packageName) : undefined); 56 } 57} 58