forked from microsoft/TypeScript
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathsuggestionDiagnostics.ts
81 lines (71 loc) · 4.12 KB
/
suggestionDiagnostics.ts
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
77
78
79
80
81
/* @internal */
namespace ts {
export function computeSuggestionDiagnostics(sourceFile: SourceFile, program: Program): Diagnostic[] {
program.getSemanticDiagnostics(sourceFile);
const checker = program.getDiagnosticsProducingTypeChecker();
const diags: Diagnostic[] = [];
if (sourceFile.commonJsModuleIndicator && (programContainsEs6Modules(program) || compilerOptionsIndicateEs6Modules(program.getCompilerOptions()))) {
diags.push(createDiagnosticForNode(getErrorNodeFromCommonJsIndicator(sourceFile.commonJsModuleIndicator), Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module));
}
const isJsFile = isSourceFileJavaScript(sourceFile);
function check(node: Node) {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
if (isJsFile) {
const symbol = node.symbol;
if (symbol.members && (symbol.members.size > 0)) {
diags.push(createDiagnosticForNode(isVariableDeclaration(node.parent) ? node.parent.name : node, Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration));
}
}
break;
}
if (!isJsFile && codefix.parameterShouldGetTypeFromJSDoc(node)) {
diags.push(createDiagnosticForNode(node.name || node, Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types));
}
node.forEachChild(check);
}
check(sourceFile);
if (!isJsFile) {
for (const statement of sourceFile.statements) {
if (isVariableStatement(statement) &&
statement.declarationList.flags & NodeFlags.Const &&
statement.declarationList.declarations.length === 1) {
const init = statement.declarationList.declarations[0].initializer;
if (init && isRequireCall(init, /*checkArgumentIsStringLiteralLike*/ true)) {
diags.push(createDiagnosticForNode(init, Diagnostics.require_call_may_be_converted_to_an_import));
}
}
}
}
if (getAllowSyntheticDefaultImports(program.getCompilerOptions())) {
for (const moduleSpecifier of sourceFile.imports) {
const importNode = importFromModuleSpecifier(moduleSpecifier);
const name = importNameForConvertToDefaultImport(importNode);
if (!name) continue;
const module = getResolvedModule(sourceFile, moduleSpecifier.text);
const resolvedFile = module && program.getSourceFile(module.resolvedFileName);
if (resolvedFile && resolvedFile.externalModuleIndicator && isExportAssignment(resolvedFile.externalModuleIndicator) && resolvedFile.externalModuleIndicator.isExportEquals) {
diags.push(createDiagnosticForNode(name, Diagnostics.Import_may_be_converted_to_a_default_import));
}
}
}
return diags.concat(checker.getSuggestionDiagnostics(sourceFile));
}
function importNameForConvertToDefaultImport(node: AnyValidImportOrReExport): Identifier | undefined {
switch (node.kind) {
case SyntaxKind.ImportDeclaration:
const { importClause, moduleSpecifier } = node;
return importClause && !importClause.name && importClause.namedBindings.kind === SyntaxKind.NamespaceImport && isStringLiteral(moduleSpecifier)
? importClause.namedBindings.name
: undefined;
case SyntaxKind.ImportEqualsDeclaration:
return node.name;
default:
return undefined;
}
}
function getErrorNodeFromCommonJsIndicator(commonJsModuleIndicator: Node): Node {
return isBinaryExpression(commonJsModuleIndicator) ? commonJsModuleIndicator.left : commonJsModuleIndicator;
}
}