forked from microsoft/TypeScript
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathfixCannotFindModule.ts
More file actions
76 lines (71 loc) · 3.21 KB
/
fixCannotFindModule.ts
File metadata and controls
76 lines (71 loc) · 3.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import {
codeFixAll,
createCodeFixAction,
registerCodeFix,
} from "../_namespaces/ts.codefix.js";
import {
Debug,
Diagnostics,
getTokenAtPosition,
getTypesPackageName,
InstallPackageAction,
isExternalModuleNameRelative,
isStringLiteral,
JsTyping,
LanguageServiceHost,
parsePackageName,
SourceFile,
tryCast,
} from "../_namespaces/ts.js";
const fixName = "fixCannotFindModule";
const fixIdInstallTypesPackage = "installTypesPackage";
const errorCodeCannotFindModule = Diagnostics.Cannot_find_module_0_or_its_corresponding_type_declarations.code;
const errorCodes = [
errorCodeCannotFindModule,
Diagnostics.Could_not_find_a_declaration_file_for_module_0_1_implicitly_has_an_any_type.code,
];
registerCodeFix({
errorCodes,
getCodeActions: function getCodeActionsToFixNotFoundModule(context) {
const { host, sourceFile, span: { start } } = context;
const packageName = tryGetImportedPackageName(sourceFile, start);
if (packageName === undefined) return undefined;
const typesPackageName = getTypesPackageNameToInstall(packageName, host, context.errorCode);
return typesPackageName === undefined
? []
: [createCodeFixAction(fixName, /*changes*/ [], [Diagnostics.Install_0, typesPackageName], fixIdInstallTypesPackage, Diagnostics.Install_all_missing_types_packages, getInstallCommand(sourceFile.fileName, typesPackageName))];
},
fixIds: [fixIdInstallTypesPackage],
getAllCodeActions: context => {
return codeFixAll(context, errorCodes, (_changes, diag, commands) => {
const packageName = tryGetImportedPackageName(diag.file, diag.start);
if (packageName === undefined) return undefined;
switch (context.fixId) {
case fixIdInstallTypesPackage: {
const pkg = getTypesPackageNameToInstall(packageName, context.host, diag.code);
if (pkg) {
commands.push(getInstallCommand(diag.file.fileName, pkg));
}
break;
}
default:
Debug.fail(`Bad fixId: ${context.fixId}`);
}
});
},
});
function getInstallCommand(fileName: string, packageName: string): InstallPackageAction {
return { type: "install package", file: fileName, packageName };
}
function tryGetImportedPackageName(sourceFile: SourceFile, pos: number): string | undefined {
const moduleSpecifierText = tryCast(getTokenAtPosition(sourceFile, pos), isStringLiteral);
if (!moduleSpecifierText) return undefined;
const moduleName = moduleSpecifierText.text;
const { packageName } = parsePackageName(moduleName);
return isExternalModuleNameRelative(packageName) ? undefined : packageName;
}
function getTypesPackageNameToInstall(packageName: string, host: LanguageServiceHost, diagCode: number): string | undefined {
return diagCode === errorCodeCannotFindModule
? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined)
: (host.isKnownTypesPackageName?.(packageName) ? getTypesPackageName(packageName) : undefined);
}