From 8995126563f1bcb441526b4f8490bc791d7a4b5a Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 21 May 2018 16:15:57 -0700 Subject: [PATCH] Update LKG --- lib/enu/diagnosticMessages.generated.json.lcg | 12 ++ lib/tsc.js | 90 +++++++---- lib/tsserver.js | 147 +++++++++++------- lib/tsserverlibrary.js | 147 +++++++++++------- lib/typescript.js | 147 +++++++++++------- lib/typescriptServices.js | 147 +++++++++++------- lib/typingsInstaller.js | 2 + 7 files changed, 449 insertions(+), 243 deletions(-) diff --git a/lib/enu/diagnosticMessages.generated.json.lcg b/lib/enu/diagnosticMessages.generated.json.lcg index 3ea2129b89b..c0e6b02d916 100644 --- a/lib/enu/diagnosticMessages.generated.json.lcg +++ b/lib/enu/diagnosticMessages.generated.json.lcg @@ -735,6 +735,12 @@ + + + + + + @@ -4305,6 +4311,12 @@ + + + + + + diff --git a/lib/tsc.js b/lib/tsc.js index 349217d10d0..11fd8845d40 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -4526,6 +4526,7 @@ var ts; _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -4634,6 +4635,7 @@ var ts; Implement_inherited_abstract_class: diag(90007, ts.DiagnosticCategory.Message, "Implement_inherited_abstract_class_90007", "Implement inherited abstract class"), Add_0_to_unresolved_variable: diag(90008, ts.DiagnosticCategory.Message, "Add_0_to_unresolved_variable_90008", "Add '{0}.' to unresolved variable"), Remove_destructuring: diag(90009, ts.DiagnosticCategory.Message, "Remove_destructuring_90009", "Remove destructuring"), + Remove_variable_statement: diag(90010, ts.DiagnosticCategory.Message, "Remove_variable_statement_90010", "Remove variable statement"), Import_0_from_module_1: diag(90013, ts.DiagnosticCategory.Message, "Import_0_from_module_1_90013", "Import '{0}' from module \"{1}\""), Change_0_to_1: diag(90014, ts.DiagnosticCategory.Message, "Change_0_to_1_90014", "Change '{0}' to '{1}'"), Add_0_to_existing_import_declaration_from_1: diag(90015, ts.DiagnosticCategory.Message, "Add_0_to_existing_import_declaration_from_1_90015", "Add '{0}' to existing import declaration from \"{1}\""), @@ -38935,13 +38937,6 @@ var ts; } function errorUnusedLocal(declaration, name, addDiagnostic) { var node = ts.getNameOfDeclaration(declaration) || declaration; - if (isIdentifierThatStartsWithUnderScore(node)) { - var declaration_2 = ts.getRootDeclaration(node.parent); - if ((declaration_2.kind === 231 && ts.isForInOrOfStatement(declaration_2.parent.parent)) || - declaration_2.kind === 147) { - return; - } - } var message = isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; addDiagnostic(0, ts.createDiagnosticForNodeSpan(ts.getSourceFileOfNode(declaration), declaration, node, message, name)); } @@ -39014,6 +39009,7 @@ var ts; return; var unusedImports = ts.createMap(); var unusedDestructures = ts.createMap(); + var unusedVariables = ts.createMap(); nodeWithLocals.locals.forEach(function (local) { if (local.flags & 262144 ? !(local.flags & 3 && !(local.isReferenced & 3)) : local.isReferenced || local.exportSymbol) { return; @@ -39031,6 +39027,11 @@ var ts; addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } } + else if (ts.isVariableDeclaration(declaration)) { + if (!isIdentifierThatStartsWithUnderScore(declaration.name) || !ts.isForInOrOfStatement(declaration.parent.parent)) { + addToGroup(unusedVariables, declaration.parent, declaration, getNodeId); + } + } else { var parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); if (parameter) { @@ -39048,47 +39049,74 @@ var ts; unusedImports.forEach(function (_a) { var importClause = _a[0], unuseds = _a[1]; var importDecl = importClause.parent; - if (forEachImportedDeclaration(importClause, function (d) { return !ts.contains(unuseds, d); })) { + var nDeclarations = (importClause.name ? 1 : 0) + + (importClause.namedBindings ? + (importClause.namedBindings.kind === 245 ? 1 : importClause.namedBindings.elements.length) + : 0); + if (nDeclarations === unuseds.length) { + addDiagnostic(0, unuseds.length === 1 + ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name)) + : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); + } + else { for (var _i = 0, unuseds_1 = unuseds; _i < unuseds_1.length; _i++) { var unused = unuseds_1[_i]; errorUnusedLocal(unused, ts.idText(unused.name), addDiagnostic); } } - else if (unuseds.length === 1) { - addDiagnostic(0, ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name))); - } - else { - addDiagnostic(0, ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); - } }); unusedDestructures.forEach(function (_a) { var bindingPattern = _a[0], bindingElements = _a[1]; var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 : 0; - if (!bindingPattern.elements.every(function (e) { return ts.contains(bindingElements, e); })) { + if (bindingPattern.elements.length === bindingElements.length) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === 231 && bindingPattern.parent.parent.kind === 232) { + addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); + } + else { + addDiagnostic(kind, bindingElements.length === 1 + ? ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier))) + : ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + } + } + else { for (var _i = 0, bindingElements_1 = bindingElements; _i < bindingElements_1.length; _i++) { var e = bindingElements_1[_i]; addDiagnostic(kind, ts.createDiagnosticForNode(e, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(e.name, ts.isIdentifier)))); } } - else if (bindingElements.length === 1) { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier)))); + }); + unusedVariables.forEach(function (_a) { + var declarationList = _a[0], declarations = _a[1]; + if (declarationList.declarations.length === declarations.length) { + addDiagnostic(0, declarations.length === 1 + ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) + : ts.createDiagnosticForNode(declarationList.parent.kind === 213 ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); } else { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { + var decl = declarations_5[_i]; + addDiagnostic(0, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); + } } }); } + function bindingNameText(name) { + switch (name.kind) { + case 71: + return ts.idText(name); + case 180: + case 179: + return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); + default: + return ts.Debug.assertNever(name); + } + } function isImportedDeclaration(node) { return node.kind === 244 || node.kind === 247 || node.kind === 245; } function importClauseFromImported(decl) { return decl.kind === 244 ? decl : decl.kind === 245 ? decl.parent : decl.parent.parent; } - function forEachImportedDeclaration(importClause, cb) { - var defaultName = importClause.name, namedBindings = importClause.namedBindings; - return (defaultName && cb(importClause)) || - namedBindings && (namedBindings.kind === 245 ? cb(namedBindings) : ts.forEach(namedBindings.elements, cb)); - } function checkBlock(node) { if (node.kind === 212) { checkGrammarStatementInAmbientContext(node); @@ -39983,8 +40011,8 @@ var ts; var type = getDeclaredTypeOfSymbol(symbol); if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { var name = symbolToString(symbol); - for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { - var declaration = declarations_5[_i]; + for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { + var declaration = declarations_6[_i]; error(declaration.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); } } @@ -39993,8 +40021,8 @@ var ts; function areTypeParametersIdentical(declarations, targetParameters) { var maxTypeArgumentCount = ts.length(targetParameters); var minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); - for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { - var declaration = declarations_6[_i]; + for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { + var declaration = declarations_7[_i]; var sourceParameters = ts.getEffectiveTypeParameterDeclarations(declaration); var numTypeParameters = sourceParameters.length; if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) { @@ -40527,8 +40555,8 @@ var ts; } function getFirstNonAmbientClassOrFunctionDeclaration(symbol) { var declarations = symbol.declarations; - for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { - var declaration = declarations_7[_i]; + for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { + var declaration = declarations_8[_i]; if ((declaration.kind === 234 || (declaration.kind === 233 && ts.nodeIsPresent(declaration.body))) && !(declaration.flags & 4194304)) { @@ -40917,8 +40945,8 @@ var ts; return; } if (exportedDeclarationsCount > 1) { - for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { - var declaration = declarations_8[_i]; + for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { + var declaration = declarations_9[_i]; if (isNotOverload(declaration)) { diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Cannot_redeclare_exported_variable_0, ts.unescapeLeadingUnderscores(id))); } diff --git a/lib/tsserver.js b/lib/tsserver.js index b60185f3458..b54723f6129 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -5758,6 +5758,7 @@ var ts; _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -5866,6 +5867,7 @@ var ts; Implement_inherited_abstract_class: diag(90007, ts.DiagnosticCategory.Message, "Implement_inherited_abstract_class_90007", "Implement inherited abstract class"), Add_0_to_unresolved_variable: diag(90008, ts.DiagnosticCategory.Message, "Add_0_to_unresolved_variable_90008", "Add '{0}.' to unresolved variable"), Remove_destructuring: diag(90009, ts.DiagnosticCategory.Message, "Remove_destructuring_90009", "Remove destructuring"), + Remove_variable_statement: diag(90010, ts.DiagnosticCategory.Message, "Remove_variable_statement_90010", "Remove variable statement"), Import_0_from_module_1: diag(90013, ts.DiagnosticCategory.Message, "Import_0_from_module_1_90013", "Import '{0}' from module \"{1}\""), Change_0_to_1: diag(90014, ts.DiagnosticCategory.Message, "Change_0_to_1_90014", "Change '{0}' to '{1}'"), Add_0_to_existing_import_declaration_from_1: diag(90015, ts.DiagnosticCategory.Message, "Add_0_to_existing_import_declaration_from_1_90015", "Add '{0}' to existing import declaration from \"{1}\""), @@ -40392,13 +40394,6 @@ var ts; } function errorUnusedLocal(declaration, name, addDiagnostic) { var node = ts.getNameOfDeclaration(declaration) || declaration; - if (isIdentifierThatStartsWithUnderScore(node)) { - var declaration_2 = ts.getRootDeclaration(node.parent); - if ((declaration_2.kind === 231 && ts.isForInOrOfStatement(declaration_2.parent.parent)) || - declaration_2.kind === 147) { - return; - } - } var message = isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; addDiagnostic(0, ts.createDiagnosticForNodeSpan(ts.getSourceFileOfNode(declaration), declaration, node, message, name)); } @@ -40471,6 +40466,7 @@ var ts; return; var unusedImports = ts.createMap(); var unusedDestructures = ts.createMap(); + var unusedVariables = ts.createMap(); nodeWithLocals.locals.forEach(function (local) { if (local.flags & 262144 ? !(local.flags & 3 && !(local.isReferenced & 3)) : local.isReferenced || local.exportSymbol) { return; @@ -40488,6 +40484,11 @@ var ts; addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } } + else if (ts.isVariableDeclaration(declaration)) { + if (!isIdentifierThatStartsWithUnderScore(declaration.name) || !ts.isForInOrOfStatement(declaration.parent.parent)) { + addToGroup(unusedVariables, declaration.parent, declaration, getNodeId); + } + } else { var parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); if (parameter) { @@ -40505,47 +40506,74 @@ var ts; unusedImports.forEach(function (_a) { var importClause = _a[0], unuseds = _a[1]; var importDecl = importClause.parent; - if (forEachImportedDeclaration(importClause, function (d) { return !ts.contains(unuseds, d); })) { + var nDeclarations = (importClause.name ? 1 : 0) + + (importClause.namedBindings ? + (importClause.namedBindings.kind === 245 ? 1 : importClause.namedBindings.elements.length) + : 0); + if (nDeclarations === unuseds.length) { + addDiagnostic(0, unuseds.length === 1 + ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name)) + : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); + } + else { for (var _i = 0, unuseds_1 = unuseds; _i < unuseds_1.length; _i++) { var unused = unuseds_1[_i]; errorUnusedLocal(unused, ts.idText(unused.name), addDiagnostic); } } - else if (unuseds.length === 1) { - addDiagnostic(0, ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name))); - } - else { - addDiagnostic(0, ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); - } }); unusedDestructures.forEach(function (_a) { var bindingPattern = _a[0], bindingElements = _a[1]; var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 : 0; - if (!bindingPattern.elements.every(function (e) { return ts.contains(bindingElements, e); })) { + if (bindingPattern.elements.length === bindingElements.length) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === 231 && bindingPattern.parent.parent.kind === 232) { + addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); + } + else { + addDiagnostic(kind, bindingElements.length === 1 + ? ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier))) + : ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + } + } + else { for (var _i = 0, bindingElements_1 = bindingElements; _i < bindingElements_1.length; _i++) { var e = bindingElements_1[_i]; addDiagnostic(kind, ts.createDiagnosticForNode(e, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(e.name, ts.isIdentifier)))); } } - else if (bindingElements.length === 1) { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier)))); + }); + unusedVariables.forEach(function (_a) { + var declarationList = _a[0], declarations = _a[1]; + if (declarationList.declarations.length === declarations.length) { + addDiagnostic(0, declarations.length === 1 + ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) + : ts.createDiagnosticForNode(declarationList.parent.kind === 213 ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); } else { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { + var decl = declarations_5[_i]; + addDiagnostic(0, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); + } } }); } + function bindingNameText(name) { + switch (name.kind) { + case 71: + return ts.idText(name); + case 180: + case 179: + return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); + default: + return ts.Debug.assertNever(name); + } + } function isImportedDeclaration(node) { return node.kind === 244 || node.kind === 247 || node.kind === 245; } function importClauseFromImported(decl) { return decl.kind === 244 ? decl : decl.kind === 245 ? decl.parent : decl.parent.parent; } - function forEachImportedDeclaration(importClause, cb) { - var defaultName = importClause.name, namedBindings = importClause.namedBindings; - return (defaultName && cb(importClause)) || - namedBindings && (namedBindings.kind === 245 ? cb(namedBindings) : ts.forEach(namedBindings.elements, cb)); - } function checkBlock(node) { if (node.kind === 212) { checkGrammarStatementInAmbientContext(node); @@ -41440,8 +41468,8 @@ var ts; var type = getDeclaredTypeOfSymbol(symbol); if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { var name = symbolToString(symbol); - for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { - var declaration = declarations_5[_i]; + for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { + var declaration = declarations_6[_i]; error(declaration.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); } } @@ -41450,8 +41478,8 @@ var ts; function areTypeParametersIdentical(declarations, targetParameters) { var maxTypeArgumentCount = ts.length(targetParameters); var minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); - for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { - var declaration = declarations_6[_i]; + for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { + var declaration = declarations_7[_i]; var sourceParameters = ts.getEffectiveTypeParameterDeclarations(declaration); var numTypeParameters = sourceParameters.length; if (numTypeParameters < minTypeArgumentCount || numTypeParameters > maxTypeArgumentCount) { @@ -41984,8 +42012,8 @@ var ts; } function getFirstNonAmbientClassOrFunctionDeclaration(symbol) { var declarations = symbol.declarations; - for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { - var declaration = declarations_7[_i]; + for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { + var declaration = declarations_8[_i]; if ((declaration.kind === 234 || (declaration.kind === 233 && ts.nodeIsPresent(declaration.body))) && !(declaration.flags & 4194304)) { @@ -42374,8 +42402,8 @@ var ts; return; } if (exportedDeclarationsCount > 1) { - for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { - var declaration = declarations_8[_i]; + for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { + var declaration = declarations_9[_i]; if (isNotOverload(declaration)) { diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Cannot_redeclare_exported_variable_0, ts.unescapeLeadingUnderscores(id))); } @@ -75714,8 +75742,8 @@ var ts; return undefined; } var scope; - for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { - var declaration = declarations_9[_i]; + for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { + var declaration = declarations_10[_i]; var container = ts.getContainerNode(declaration); if (scope && scope !== container) { return undefined; @@ -76274,8 +76302,8 @@ var ts; var lastIterationMeaning = void 0; do { lastIterationMeaning = meaning; - for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { - var declaration = declarations_10[_i]; + for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { + var declaration = declarations_11[_i]; var declarationMeaning = ts.getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -77174,8 +77202,8 @@ var ts; if (!match) { return; } - for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { - var declaration = declarations_11[_i]; + for (var _i = 0, declarations_12 = declarations; _i < declarations_12.length; _i++) { + var declaration = declarations_12[_i]; if (!shouldKeepItem(declaration, checker)) continue; if (patternMatcher.patternContainsDots) { @@ -79051,8 +79079,8 @@ var ts; } } }; - for (var _b = 0, declarations_12 = declarations; _b < declarations_12.length; _b++) { - var declaration = declarations_12[_b]; + for (var _b = 0, declarations_13 = declarations; _b < declarations_13.length; _b++) { + var declaration = declarations_13[_b]; var state_5 = _loop_16(declaration); if (typeof state_5 === "object") return state_5.value; @@ -84846,20 +84874,26 @@ var ts; ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code, ts.Diagnostics.All_imports_in_import_declaration_are_unused.code, ts.Diagnostics.All_destructured_elements_are_unused.code, + ts.Diagnostics.All_variables_are_unused.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var errorCode = context.errorCode, sourceFile = context.sourceFile; - var importDecl = tryGetFullImport(sourceFile, context.span.start); + var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, false); + var importDecl = tryGetFullImport(startToken); if (importDecl) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.deleteNode(sourceFile, importDecl); }); return [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, context.span.start, undefined); }); + var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, undefined); }); if (delDestructure.length) { return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_destructuring, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } + var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, undefined); }); + if (delVar.length) { + return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_variable_statement, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; + } var token = getToken(sourceFile, ts.textSpanEnd(context.span)); var result = []; var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, undefined); }); @@ -84877,6 +84911,7 @@ var ts; var deleted = new NodeSet(); return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var sourceFile = context.sourceFile; + var startToken = ts.getTokenAtPosition(sourceFile, diag.start, false); var token = ts.findPrecedingToken(ts.textSpanEnd(diag), diag.file); switch (context.fixId) { case fixIdPrefix: @@ -84887,14 +84922,12 @@ var ts; case fixIdDelete: if (deleted.some(function (d) { return ts.rangeContainsPosition(d, diag.start); })) break; - var importDecl = tryGetFullImport(diag.file, diag.start); + var importDecl = tryGetFullImport(startToken); if (importDecl) { changes.deleteNode(sourceFile, importDecl); } - else { - if (!tryDeleteFullDestructure(changes, sourceFile, diag.start, deleted)) { - tryDeleteDeclaration(changes, sourceFile, token, deleted); - } + else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted) && !tryDeleteFullVariableStatement(changes, sourceFile, startToken, deleted)) { + tryDeleteDeclaration(changes, sourceFile, token, deleted); } break; default: @@ -84903,15 +84936,13 @@ var ts; }); }, }); - function tryGetFullImport(sourceFile, pos) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, false); + function tryGetFullImport(startToken) { return startToken.kind === 91 ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; } - function tryDeleteFullDestructure(changes, sourceFile, pos, deletedAncestors) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, false); + function tryDeleteFullDestructure(changes, sourceFile, startToken, deletedAncestors) { if (startToken.kind !== 17 || !ts.isObjectBindingPattern(startToken.parent)) return false; - var decl = startToken.parent.parent; + var decl = ts.cast(startToken.parent, ts.isObjectBindingPattern).parent; switch (decl.kind) { case 231: tryDeleteVariableDeclaration(changes, sourceFile, decl, deletedAncestors); @@ -84931,6 +84962,16 @@ var ts; } return true; } + function tryDeleteFullVariableStatement(changes, sourceFile, startToken, deletedAncestors) { + var declarationList = ts.tryCast(startToken.parent, ts.isVariableDeclarationList); + if (declarationList && declarationList.getChildren(sourceFile)[0] === startToken) { + if (deletedAncestors) + deletedAncestors.add(declarationList); + changes.deleteNode(sourceFile, declarationList.parent.kind === 213 ? declarationList.parent : declarationList); + return true; + } + return false; + } function getToken(sourceFile, pos) { var token = ts.findPrecedingToken(pos, sourceFile, undefined, true); return token.kind === 22 ? ts.findPrecedingToken(pos - 1, sourceFile) : token; @@ -89222,8 +89263,8 @@ var ts; return ts.emptyArray; var doc = ts.JsDoc.getJsDocCommentsFromDeclarations(declarations); if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) { - for (var _i = 0, declarations_13 = declarations; _i < declarations_13.length; _i++) { - var declaration = declarations_13[_i]; + for (var _i = 0, declarations_14 = declarations; _i < declarations_14.length; _i++) { + var declaration = declarations_14[_i]; var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); if (inheritedDocs) doc = doc.length === 0 ? inheritedDocs.slice() : inheritedDocs.concat(ts.lineBreakPart(), doc); diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index bc50a754604..22e5f359e1f 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -6602,6 +6602,7 @@ var ts; _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", /*reportsUnnecessary*/ true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", /*reportsUnnecessary*/ true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", /*reportsUnnecessary*/ true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -6710,6 +6711,7 @@ var ts; Implement_inherited_abstract_class: diag(90007, ts.DiagnosticCategory.Message, "Implement_inherited_abstract_class_90007", "Implement inherited abstract class"), Add_0_to_unresolved_variable: diag(90008, ts.DiagnosticCategory.Message, "Add_0_to_unresolved_variable_90008", "Add '{0}.' to unresolved variable"), Remove_destructuring: diag(90009, ts.DiagnosticCategory.Message, "Remove_destructuring_90009", "Remove destructuring"), + Remove_variable_statement: diag(90010, ts.DiagnosticCategory.Message, "Remove_variable_statement_90010", "Remove variable statement"), Import_0_from_module_1: diag(90013, ts.DiagnosticCategory.Message, "Import_0_from_module_1_90013", "Import '{0}' from module \"{1}\""), Change_0_to_1: diag(90014, ts.DiagnosticCategory.Message, "Change_0_to_1_90014", "Change '{0}' to '{1}'"), Add_0_to_existing_import_declaration_from_1: diag(90015, ts.DiagnosticCategory.Message, "Add_0_to_existing_import_declaration_from_1_90015", "Add '{0}' to existing import declaration from \"{1}\""), @@ -47199,13 +47201,6 @@ var ts; } function errorUnusedLocal(declaration, name, addDiagnostic) { var node = ts.getNameOfDeclaration(declaration) || declaration; - if (isIdentifierThatStartsWithUnderScore(node)) { - var declaration_2 = ts.getRootDeclaration(node.parent); - if ((declaration_2.kind === 231 /* VariableDeclaration */ && ts.isForInOrOfStatement(declaration_2.parent.parent)) || - declaration_2.kind === 147 /* TypeParameter */) { - return; - } - } var message = isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; addDiagnostic(0 /* Local */, ts.createDiagnosticForNodeSpan(ts.getSourceFileOfNode(declaration), declaration, node, message, name)); } @@ -47283,6 +47278,7 @@ var ts; // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. var unusedImports = ts.createMap(); var unusedDestructures = ts.createMap(); + var unusedVariables = ts.createMap(); nodeWithLocals.locals.forEach(function (local) { // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. // If it's a type parameter merged with a parameter, check if the parameter-side is used. @@ -47303,6 +47299,11 @@ var ts; addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } } + else if (ts.isVariableDeclaration(declaration)) { + if (!isIdentifierThatStartsWithUnderScore(declaration.name) || !ts.isForInOrOfStatement(declaration.parent.parent)) { + addToGroup(unusedVariables, declaration.parent, declaration, getNodeId); + } + } else { var parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); if (parameter) { @@ -47320,47 +47321,74 @@ var ts; unusedImports.forEach(function (_a) { var importClause = _a[0], unuseds = _a[1]; var importDecl = importClause.parent; - if (forEachImportedDeclaration(importClause, function (d) { return !ts.contains(unuseds, d); })) { + var nDeclarations = (importClause.name ? 1 : 0) + + (importClause.namedBindings ? + (importClause.namedBindings.kind === 245 /* NamespaceImport */ ? 1 : importClause.namedBindings.elements.length) + : 0); + if (nDeclarations === unuseds.length) { + addDiagnostic(0 /* Local */, unuseds.length === 1 + ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name)) + : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); + } + else { for (var _i = 0, unuseds_1 = unuseds; _i < unuseds_1.length; _i++) { var unused = unuseds_1[_i]; errorUnusedLocal(unused, ts.idText(unused.name), addDiagnostic); } } - else if (unuseds.length === 1) { - addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name))); - } - else { - addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); - } }); unusedDestructures.forEach(function (_a) { var bindingPattern = _a[0], bindingElements = _a[1]; var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 /* Parameter */ : 0 /* Local */; - if (!bindingPattern.elements.every(function (e) { return ts.contains(bindingElements, e); })) { + if (bindingPattern.elements.length === bindingElements.length) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === 231 /* VariableDeclaration */ && bindingPattern.parent.parent.kind === 232 /* VariableDeclarationList */) { + addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); + } + else { + addDiagnostic(kind, bindingElements.length === 1 + ? ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier))) + : ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + } + } + else { for (var _i = 0, bindingElements_1 = bindingElements; _i < bindingElements_1.length; _i++) { var e = bindingElements_1[_i]; addDiagnostic(kind, ts.createDiagnosticForNode(e, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(e.name, ts.isIdentifier)))); } } - else if (bindingElements.length === 1) { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier)))); + }); + unusedVariables.forEach(function (_a) { + var declarationList = _a[0], declarations = _a[1]; + if (declarationList.declarations.length === declarations.length) { + addDiagnostic(0 /* Local */, declarations.length === 1 + ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) + : ts.createDiagnosticForNode(declarationList.parent.kind === 213 /* VariableStatement */ ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); } else { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { + var decl = declarations_5[_i]; + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); + } } }); } + function bindingNameText(name) { + switch (name.kind) { + case 71 /* Identifier */: + return ts.idText(name); + case 180 /* ArrayBindingPattern */: + case 179 /* ObjectBindingPattern */: + return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); + default: + return ts.Debug.assertNever(name); + } + } function isImportedDeclaration(node) { return node.kind === 244 /* ImportClause */ || node.kind === 247 /* ImportSpecifier */ || node.kind === 245 /* NamespaceImport */; } function importClauseFromImported(decl) { return decl.kind === 244 /* ImportClause */ ? decl : decl.kind === 245 /* NamespaceImport */ ? decl.parent : decl.parent.parent; } - function forEachImportedDeclaration(importClause, cb) { - var defaultName = importClause.name, namedBindings = importClause.namedBindings; - return (defaultName && cb(importClause)) || - namedBindings && (namedBindings.kind === 245 /* NamespaceImport */ ? cb(namedBindings) : ts.forEach(namedBindings.elements, cb)); - } function checkBlock(node) { // Grammar checking for SyntaxKind.Block if (node.kind === 212 /* Block */) { @@ -48509,8 +48537,8 @@ var ts; if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { // Report an error on every conflicting declaration. var name = symbolToString(symbol); - for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { - var declaration = declarations_5[_i]; + for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { + var declaration = declarations_6[_i]; error(declaration.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); } } @@ -48519,8 +48547,8 @@ var ts; function areTypeParametersIdentical(declarations, targetParameters) { var maxTypeArgumentCount = ts.length(targetParameters); var minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); - for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { - var declaration = declarations_6[_i]; + for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { + var declaration = declarations_7[_i]; // If this declaration has too few or too many type parameters, we report an error var sourceParameters = ts.getEffectiveTypeParameterDeclarations(declaration); var numTypeParameters = sourceParameters.length; @@ -49115,8 +49143,8 @@ var ts; } function getFirstNonAmbientClassOrFunctionDeclaration(symbol) { var declarations = symbol.declarations; - for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { - var declaration = declarations_7[_i]; + for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { + var declaration = declarations_8[_i]; if ((declaration.kind === 234 /* ClassDeclaration */ || (declaration.kind === 233 /* FunctionDeclaration */ && ts.nodeIsPresent(declaration.body))) && !(declaration.flags & 4194304 /* Ambient */)) { @@ -49558,8 +49586,8 @@ var ts; return; } if (exportedDeclarationsCount > 1) { - for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { - var declaration = declarations_8[_i]; + for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { + var declaration = declarations_9[_i]; if (isNotOverload(declaration)) { diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Cannot_redeclare_exported_variable_0, ts.unescapeLeadingUnderscores(id))); } @@ -90998,8 +91026,8 @@ var ts; return undefined; } var scope; - for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { - var declaration = declarations_9[_i]; + for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { + var declaration = declarations_10[_i]; var container = ts.getContainerNode(declaration); if (scope && scope !== container) { // Different declarations have different containers, bail out @@ -91712,8 +91740,8 @@ var ts; // To achieve that we will keep iterating until the result stabilizes. // Remember the last meaning lastIterationMeaning = meaning; - for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { - var declaration = declarations_10[_i]; + for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { + var declaration = declarations_11[_i]; var declarationMeaning = ts.getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -92784,8 +92812,8 @@ var ts; if (!match) { return; // continue to next named declarations } - for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { - var declaration = declarations_11[_i]; + for (var _i = 0, declarations_12 = declarations; _i < declarations_12.length; _i++) { + var declaration = declarations_12[_i]; if (!shouldKeepItem(declaration, checker)) continue; if (patternMatcher.patternContainsDots) { @@ -95002,8 +95030,8 @@ var ts; } } }; - for (var _b = 0, declarations_12 = declarations; _b < declarations_12.length; _b++) { - var declaration = declarations_12[_b]; + for (var _b = 0, declarations_13 = declarations; _b < declarations_13.length; _b++) { + var declaration = declarations_13[_b]; var state_5 = _loop_16(declaration); if (typeof state_5 === "object") return state_5.value; @@ -101659,20 +101687,26 @@ var ts; ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code, ts.Diagnostics.All_imports_in_import_declaration_are_unused.code, ts.Diagnostics.All_destructured_elements_are_unused.code, + ts.Diagnostics.All_variables_are_unused.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var errorCode = context.errorCode, sourceFile = context.sourceFile; - var importDecl = tryGetFullImport(sourceFile, context.span.start); + var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false); + var importDecl = tryGetFullImport(startToken); if (importDecl) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.deleteNode(sourceFile, importDecl); }); return [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, context.span.start, /*deleted*/ undefined); }); + var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, /*deleted*/ undefined); }); if (delDestructure.length) { return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_destructuring, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } + var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, /*deleted*/ undefined); }); + if (delVar.length) { + return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_variable_statement, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; + } var token = getToken(sourceFile, ts.textSpanEnd(context.span)); var result = []; var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, /*deleted*/ undefined); }); @@ -101691,6 +101725,7 @@ var ts; var deleted = new NodeSet(); return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var sourceFile = context.sourceFile; + var startToken = ts.getTokenAtPosition(sourceFile, diag.start, /*includeJsDocComment*/ false); var token = ts.findPrecedingToken(ts.textSpanEnd(diag), diag.file); switch (context.fixId) { case fixIdPrefix: @@ -101702,14 +101737,12 @@ var ts; // Ignore if this range was already deleted. if (deleted.some(function (d) { return ts.rangeContainsPosition(d, diag.start); })) break; - var importDecl = tryGetFullImport(diag.file, diag.start); + var importDecl = tryGetFullImport(startToken); if (importDecl) { changes.deleteNode(sourceFile, importDecl); } - else { - if (!tryDeleteFullDestructure(changes, sourceFile, diag.start, deleted)) { - tryDeleteDeclaration(changes, sourceFile, token, deleted); - } + else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted) && !tryDeleteFullVariableStatement(changes, sourceFile, startToken, deleted)) { + tryDeleteDeclaration(changes, sourceFile, token, deleted); } break; default: @@ -101719,15 +101752,13 @@ var ts; }, }); // Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing. - function tryGetFullImport(sourceFile, pos) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + function tryGetFullImport(startToken) { return startToken.kind === 91 /* ImportKeyword */ ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; } - function tryDeleteFullDestructure(changes, sourceFile, pos, deletedAncestors) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + function tryDeleteFullDestructure(changes, sourceFile, startToken, deletedAncestors) { if (startToken.kind !== 17 /* OpenBraceToken */ || !ts.isObjectBindingPattern(startToken.parent)) return false; - var decl = startToken.parent.parent; + var decl = ts.cast(startToken.parent, ts.isObjectBindingPattern).parent; switch (decl.kind) { case 231 /* VariableDeclaration */: tryDeleteVariableDeclaration(changes, sourceFile, decl, deletedAncestors); @@ -101747,6 +101778,16 @@ var ts; } return true; } + function tryDeleteFullVariableStatement(changes, sourceFile, startToken, deletedAncestors) { + var declarationList = ts.tryCast(startToken.parent, ts.isVariableDeclarationList); + if (declarationList && declarationList.getChildren(sourceFile)[0] === startToken) { + if (deletedAncestors) + deletedAncestors.add(declarationList); + changes.deleteNode(sourceFile, declarationList.parent.kind === 213 /* VariableStatement */ ? declarationList.parent : declarationList); + return true; + } + return false; + } function getToken(sourceFile, pos) { var token = ts.findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true); // this handles var ["computed"] = 12; @@ -106517,8 +106558,8 @@ var ts; return ts.emptyArray; var doc = ts.JsDoc.getJsDocCommentsFromDeclarations(declarations); if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) { - for (var _i = 0, declarations_13 = declarations; _i < declarations_13.length; _i++) { - var declaration = declarations_13[_i]; + for (var _i = 0, declarations_14 = declarations; _i < declarations_14.length; _i++) { + var declaration = declarations_14[_i]; var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs if (inheritedDocs) diff --git a/lib/typescript.js b/lib/typescript.js index bd281d5c062..5e0417f5f17 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -6602,6 +6602,7 @@ var ts; _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", /*reportsUnnecessary*/ true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", /*reportsUnnecessary*/ true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", /*reportsUnnecessary*/ true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -6710,6 +6711,7 @@ var ts; Implement_inherited_abstract_class: diag(90007, ts.DiagnosticCategory.Message, "Implement_inherited_abstract_class_90007", "Implement inherited abstract class"), Add_0_to_unresolved_variable: diag(90008, ts.DiagnosticCategory.Message, "Add_0_to_unresolved_variable_90008", "Add '{0}.' to unresolved variable"), Remove_destructuring: diag(90009, ts.DiagnosticCategory.Message, "Remove_destructuring_90009", "Remove destructuring"), + Remove_variable_statement: diag(90010, ts.DiagnosticCategory.Message, "Remove_variable_statement_90010", "Remove variable statement"), Import_0_from_module_1: diag(90013, ts.DiagnosticCategory.Message, "Import_0_from_module_1_90013", "Import '{0}' from module \"{1}\""), Change_0_to_1: diag(90014, ts.DiagnosticCategory.Message, "Change_0_to_1_90014", "Change '{0}' to '{1}'"), Add_0_to_existing_import_declaration_from_1: diag(90015, ts.DiagnosticCategory.Message, "Add_0_to_existing_import_declaration_from_1_90015", "Add '{0}' to existing import declaration from \"{1}\""), @@ -47199,13 +47201,6 @@ var ts; } function errorUnusedLocal(declaration, name, addDiagnostic) { var node = ts.getNameOfDeclaration(declaration) || declaration; - if (isIdentifierThatStartsWithUnderScore(node)) { - var declaration_2 = ts.getRootDeclaration(node.parent); - if ((declaration_2.kind === 231 /* VariableDeclaration */ && ts.isForInOrOfStatement(declaration_2.parent.parent)) || - declaration_2.kind === 147 /* TypeParameter */) { - return; - } - } var message = isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; addDiagnostic(0 /* Local */, ts.createDiagnosticForNodeSpan(ts.getSourceFileOfNode(declaration), declaration, node, message, name)); } @@ -47283,6 +47278,7 @@ var ts; // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. var unusedImports = ts.createMap(); var unusedDestructures = ts.createMap(); + var unusedVariables = ts.createMap(); nodeWithLocals.locals.forEach(function (local) { // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. // If it's a type parameter merged with a parameter, check if the parameter-side is used. @@ -47303,6 +47299,11 @@ var ts; addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } } + else if (ts.isVariableDeclaration(declaration)) { + if (!isIdentifierThatStartsWithUnderScore(declaration.name) || !ts.isForInOrOfStatement(declaration.parent.parent)) { + addToGroup(unusedVariables, declaration.parent, declaration, getNodeId); + } + } else { var parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); if (parameter) { @@ -47320,47 +47321,74 @@ var ts; unusedImports.forEach(function (_a) { var importClause = _a[0], unuseds = _a[1]; var importDecl = importClause.parent; - if (forEachImportedDeclaration(importClause, function (d) { return !ts.contains(unuseds, d); })) { + var nDeclarations = (importClause.name ? 1 : 0) + + (importClause.namedBindings ? + (importClause.namedBindings.kind === 245 /* NamespaceImport */ ? 1 : importClause.namedBindings.elements.length) + : 0); + if (nDeclarations === unuseds.length) { + addDiagnostic(0 /* Local */, unuseds.length === 1 + ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name)) + : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); + } + else { for (var _i = 0, unuseds_1 = unuseds; _i < unuseds_1.length; _i++) { var unused = unuseds_1[_i]; errorUnusedLocal(unused, ts.idText(unused.name), addDiagnostic); } } - else if (unuseds.length === 1) { - addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name))); - } - else { - addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); - } }); unusedDestructures.forEach(function (_a) { var bindingPattern = _a[0], bindingElements = _a[1]; var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 /* Parameter */ : 0 /* Local */; - if (!bindingPattern.elements.every(function (e) { return ts.contains(bindingElements, e); })) { + if (bindingPattern.elements.length === bindingElements.length) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === 231 /* VariableDeclaration */ && bindingPattern.parent.parent.kind === 232 /* VariableDeclarationList */) { + addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); + } + else { + addDiagnostic(kind, bindingElements.length === 1 + ? ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier))) + : ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + } + } + else { for (var _i = 0, bindingElements_1 = bindingElements; _i < bindingElements_1.length; _i++) { var e = bindingElements_1[_i]; addDiagnostic(kind, ts.createDiagnosticForNode(e, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(e.name, ts.isIdentifier)))); } } - else if (bindingElements.length === 1) { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier)))); + }); + unusedVariables.forEach(function (_a) { + var declarationList = _a[0], declarations = _a[1]; + if (declarationList.declarations.length === declarations.length) { + addDiagnostic(0 /* Local */, declarations.length === 1 + ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) + : ts.createDiagnosticForNode(declarationList.parent.kind === 213 /* VariableStatement */ ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); } else { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { + var decl = declarations_5[_i]; + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); + } } }); } + function bindingNameText(name) { + switch (name.kind) { + case 71 /* Identifier */: + return ts.idText(name); + case 180 /* ArrayBindingPattern */: + case 179 /* ObjectBindingPattern */: + return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); + default: + return ts.Debug.assertNever(name); + } + } function isImportedDeclaration(node) { return node.kind === 244 /* ImportClause */ || node.kind === 247 /* ImportSpecifier */ || node.kind === 245 /* NamespaceImport */; } function importClauseFromImported(decl) { return decl.kind === 244 /* ImportClause */ ? decl : decl.kind === 245 /* NamespaceImport */ ? decl.parent : decl.parent.parent; } - function forEachImportedDeclaration(importClause, cb) { - var defaultName = importClause.name, namedBindings = importClause.namedBindings; - return (defaultName && cb(importClause)) || - namedBindings && (namedBindings.kind === 245 /* NamespaceImport */ ? cb(namedBindings) : ts.forEach(namedBindings.elements, cb)); - } function checkBlock(node) { // Grammar checking for SyntaxKind.Block if (node.kind === 212 /* Block */) { @@ -48509,8 +48537,8 @@ var ts; if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { // Report an error on every conflicting declaration. var name = symbolToString(symbol); - for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { - var declaration = declarations_5[_i]; + for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { + var declaration = declarations_6[_i]; error(declaration.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); } } @@ -48519,8 +48547,8 @@ var ts; function areTypeParametersIdentical(declarations, targetParameters) { var maxTypeArgumentCount = ts.length(targetParameters); var minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); - for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { - var declaration = declarations_6[_i]; + for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { + var declaration = declarations_7[_i]; // If this declaration has too few or too many type parameters, we report an error var sourceParameters = ts.getEffectiveTypeParameterDeclarations(declaration); var numTypeParameters = sourceParameters.length; @@ -49115,8 +49143,8 @@ var ts; } function getFirstNonAmbientClassOrFunctionDeclaration(symbol) { var declarations = symbol.declarations; - for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { - var declaration = declarations_7[_i]; + for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { + var declaration = declarations_8[_i]; if ((declaration.kind === 234 /* ClassDeclaration */ || (declaration.kind === 233 /* FunctionDeclaration */ && ts.nodeIsPresent(declaration.body))) && !(declaration.flags & 4194304 /* Ambient */)) { @@ -49558,8 +49586,8 @@ var ts; return; } if (exportedDeclarationsCount > 1) { - for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { - var declaration = declarations_8[_i]; + for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { + var declaration = declarations_9[_i]; if (isNotOverload(declaration)) { diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Cannot_redeclare_exported_variable_0, ts.unescapeLeadingUnderscores(id))); } @@ -90998,8 +91026,8 @@ var ts; return undefined; } var scope; - for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { - var declaration = declarations_9[_i]; + for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { + var declaration = declarations_10[_i]; var container = ts.getContainerNode(declaration); if (scope && scope !== container) { // Different declarations have different containers, bail out @@ -91712,8 +91740,8 @@ var ts; // To achieve that we will keep iterating until the result stabilizes. // Remember the last meaning lastIterationMeaning = meaning; - for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { - var declaration = declarations_10[_i]; + for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { + var declaration = declarations_11[_i]; var declarationMeaning = ts.getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -92784,8 +92812,8 @@ var ts; if (!match) { return; // continue to next named declarations } - for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { - var declaration = declarations_11[_i]; + for (var _i = 0, declarations_12 = declarations; _i < declarations_12.length; _i++) { + var declaration = declarations_12[_i]; if (!shouldKeepItem(declaration, checker)) continue; if (patternMatcher.patternContainsDots) { @@ -95002,8 +95030,8 @@ var ts; } } }; - for (var _b = 0, declarations_12 = declarations; _b < declarations_12.length; _b++) { - var declaration = declarations_12[_b]; + for (var _b = 0, declarations_13 = declarations; _b < declarations_13.length; _b++) { + var declaration = declarations_13[_b]; var state_5 = _loop_16(declaration); if (typeof state_5 === "object") return state_5.value; @@ -101659,20 +101687,26 @@ var ts; ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code, ts.Diagnostics.All_imports_in_import_declaration_are_unused.code, ts.Diagnostics.All_destructured_elements_are_unused.code, + ts.Diagnostics.All_variables_are_unused.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var errorCode = context.errorCode, sourceFile = context.sourceFile; - var importDecl = tryGetFullImport(sourceFile, context.span.start); + var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false); + var importDecl = tryGetFullImport(startToken); if (importDecl) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.deleteNode(sourceFile, importDecl); }); return [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, context.span.start, /*deleted*/ undefined); }); + var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, /*deleted*/ undefined); }); if (delDestructure.length) { return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_destructuring, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } + var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, /*deleted*/ undefined); }); + if (delVar.length) { + return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_variable_statement, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; + } var token = getToken(sourceFile, ts.textSpanEnd(context.span)); var result = []; var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, /*deleted*/ undefined); }); @@ -101691,6 +101725,7 @@ var ts; var deleted = new NodeSet(); return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var sourceFile = context.sourceFile; + var startToken = ts.getTokenAtPosition(sourceFile, diag.start, /*includeJsDocComment*/ false); var token = ts.findPrecedingToken(ts.textSpanEnd(diag), diag.file); switch (context.fixId) { case fixIdPrefix: @@ -101702,14 +101737,12 @@ var ts; // Ignore if this range was already deleted. if (deleted.some(function (d) { return ts.rangeContainsPosition(d, diag.start); })) break; - var importDecl = tryGetFullImport(diag.file, diag.start); + var importDecl = tryGetFullImport(startToken); if (importDecl) { changes.deleteNode(sourceFile, importDecl); } - else { - if (!tryDeleteFullDestructure(changes, sourceFile, diag.start, deleted)) { - tryDeleteDeclaration(changes, sourceFile, token, deleted); - } + else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted) && !tryDeleteFullVariableStatement(changes, sourceFile, startToken, deleted)) { + tryDeleteDeclaration(changes, sourceFile, token, deleted); } break; default: @@ -101719,15 +101752,13 @@ var ts; }, }); // Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing. - function tryGetFullImport(sourceFile, pos) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + function tryGetFullImport(startToken) { return startToken.kind === 91 /* ImportKeyword */ ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; } - function tryDeleteFullDestructure(changes, sourceFile, pos, deletedAncestors) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + function tryDeleteFullDestructure(changes, sourceFile, startToken, deletedAncestors) { if (startToken.kind !== 17 /* OpenBraceToken */ || !ts.isObjectBindingPattern(startToken.parent)) return false; - var decl = startToken.parent.parent; + var decl = ts.cast(startToken.parent, ts.isObjectBindingPattern).parent; switch (decl.kind) { case 231 /* VariableDeclaration */: tryDeleteVariableDeclaration(changes, sourceFile, decl, deletedAncestors); @@ -101747,6 +101778,16 @@ var ts; } return true; } + function tryDeleteFullVariableStatement(changes, sourceFile, startToken, deletedAncestors) { + var declarationList = ts.tryCast(startToken.parent, ts.isVariableDeclarationList); + if (declarationList && declarationList.getChildren(sourceFile)[0] === startToken) { + if (deletedAncestors) + deletedAncestors.add(declarationList); + changes.deleteNode(sourceFile, declarationList.parent.kind === 213 /* VariableStatement */ ? declarationList.parent : declarationList); + return true; + } + return false; + } function getToken(sourceFile, pos) { var token = ts.findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true); // this handles var ["computed"] = 12; @@ -106517,8 +106558,8 @@ var ts; return ts.emptyArray; var doc = ts.JsDoc.getJsDocCommentsFromDeclarations(declarations); if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) { - for (var _i = 0, declarations_13 = declarations; _i < declarations_13.length; _i++) { - var declaration = declarations_13[_i]; + for (var _i = 0, declarations_14 = declarations; _i < declarations_14.length; _i++) { + var declaration = declarations_14[_i]; var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs if (inheritedDocs) diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index bd281d5c062..5e0417f5f17 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -6602,6 +6602,7 @@ var ts; _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", /*reportsUnnecessary*/ true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", /*reportsUnnecessary*/ true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", /*reportsUnnecessary*/ true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -6710,6 +6711,7 @@ var ts; Implement_inherited_abstract_class: diag(90007, ts.DiagnosticCategory.Message, "Implement_inherited_abstract_class_90007", "Implement inherited abstract class"), Add_0_to_unresolved_variable: diag(90008, ts.DiagnosticCategory.Message, "Add_0_to_unresolved_variable_90008", "Add '{0}.' to unresolved variable"), Remove_destructuring: diag(90009, ts.DiagnosticCategory.Message, "Remove_destructuring_90009", "Remove destructuring"), + Remove_variable_statement: diag(90010, ts.DiagnosticCategory.Message, "Remove_variable_statement_90010", "Remove variable statement"), Import_0_from_module_1: diag(90013, ts.DiagnosticCategory.Message, "Import_0_from_module_1_90013", "Import '{0}' from module \"{1}\""), Change_0_to_1: diag(90014, ts.DiagnosticCategory.Message, "Change_0_to_1_90014", "Change '{0}' to '{1}'"), Add_0_to_existing_import_declaration_from_1: diag(90015, ts.DiagnosticCategory.Message, "Add_0_to_existing_import_declaration_from_1_90015", "Add '{0}' to existing import declaration from \"{1}\""), @@ -47199,13 +47201,6 @@ var ts; } function errorUnusedLocal(declaration, name, addDiagnostic) { var node = ts.getNameOfDeclaration(declaration) || declaration; - if (isIdentifierThatStartsWithUnderScore(node)) { - var declaration_2 = ts.getRootDeclaration(node.parent); - if ((declaration_2.kind === 231 /* VariableDeclaration */ && ts.isForInOrOfStatement(declaration_2.parent.parent)) || - declaration_2.kind === 147 /* TypeParameter */) { - return; - } - } var message = isTypeDeclaration(declaration) ? ts.Diagnostics._0_is_declared_but_never_used : ts.Diagnostics._0_is_declared_but_its_value_is_never_read; addDiagnostic(0 /* Local */, ts.createDiagnosticForNodeSpan(ts.getSourceFileOfNode(declaration), declaration, node, message, name)); } @@ -47283,6 +47278,7 @@ var ts; // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. var unusedImports = ts.createMap(); var unusedDestructures = ts.createMap(); + var unusedVariables = ts.createMap(); nodeWithLocals.locals.forEach(function (local) { // If it's purely a type parameter, ignore, will be checked in `checkUnusedTypeParameters`. // If it's a type parameter merged with a parameter, check if the parameter-side is used. @@ -47303,6 +47299,11 @@ var ts; addToGroup(unusedDestructures, declaration.parent, declaration, getNodeId); } } + else if (ts.isVariableDeclaration(declaration)) { + if (!isIdentifierThatStartsWithUnderScore(declaration.name) || !ts.isForInOrOfStatement(declaration.parent.parent)) { + addToGroup(unusedVariables, declaration.parent, declaration, getNodeId); + } + } else { var parameter = local.valueDeclaration && tryGetRootParameterDeclaration(local.valueDeclaration); if (parameter) { @@ -47320,47 +47321,74 @@ var ts; unusedImports.forEach(function (_a) { var importClause = _a[0], unuseds = _a[1]; var importDecl = importClause.parent; - if (forEachImportedDeclaration(importClause, function (d) { return !ts.contains(unuseds, d); })) { + var nDeclarations = (importClause.name ? 1 : 0) + + (importClause.namedBindings ? + (importClause.namedBindings.kind === 245 /* NamespaceImport */ ? 1 : importClause.namedBindings.elements.length) + : 0); + if (nDeclarations === unuseds.length) { + addDiagnostic(0 /* Local */, unuseds.length === 1 + ? ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name)) + : ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); + } + else { for (var _i = 0, unuseds_1 = unuseds; _i < unuseds_1.length; _i++) { var unused = unuseds_1[_i]; errorUnusedLocal(unused, ts.idText(unused.name), addDiagnostic); } } - else if (unuseds.length === 1) { - addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(importDecl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.first(unuseds).name))); - } - else { - addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(importDecl, ts.Diagnostics.All_imports_in_import_declaration_are_unused)); - } }); unusedDestructures.forEach(function (_a) { var bindingPattern = _a[0], bindingElements = _a[1]; var kind = tryGetRootParameterDeclaration(bindingPattern.parent) ? 1 /* Parameter */ : 0 /* Local */; - if (!bindingPattern.elements.every(function (e) { return ts.contains(bindingElements, e); })) { + if (bindingPattern.elements.length === bindingElements.length) { + if (bindingElements.length === 1 && bindingPattern.parent.kind === 231 /* VariableDeclaration */ && bindingPattern.parent.parent.kind === 232 /* VariableDeclarationList */) { + addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId); + } + else { + addDiagnostic(kind, bindingElements.length === 1 + ? ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier))) + : ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + } + } + else { for (var _i = 0, bindingElements_1 = bindingElements; _i < bindingElements_1.length; _i++) { var e = bindingElements_1[_i]; addDiagnostic(kind, ts.createDiagnosticForNode(e, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(e.name, ts.isIdentifier)))); } } - else if (bindingElements.length === 1) { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(ts.first(bindingElements).name, ts.isIdentifier)))); + }); + unusedVariables.forEach(function (_a) { + var declarationList = _a[0], declarations = _a[1]; + if (declarationList.declarations.length === declarations.length) { + addDiagnostic(0 /* Local */, declarations.length === 1 + ? ts.createDiagnosticForNode(ts.first(declarations).name, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(ts.first(declarations).name)) + : ts.createDiagnosticForNode(declarationList.parent.kind === 213 /* VariableStatement */ ? declarationList.parent : declarationList, ts.Diagnostics.All_variables_are_unused)); } else { - addDiagnostic(kind, ts.createDiagnosticForNode(bindingPattern, ts.Diagnostics.All_destructured_elements_are_unused)); + for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { + var decl = declarations_5[_i]; + addDiagnostic(0 /* Local */, ts.createDiagnosticForNode(decl, ts.Diagnostics._0_is_declared_but_its_value_is_never_read, ts.idText(ts.cast(decl.name, ts.isIdentifier)))); + } } }); } + function bindingNameText(name) { + switch (name.kind) { + case 71 /* Identifier */: + return ts.idText(name); + case 180 /* ArrayBindingPattern */: + case 179 /* ObjectBindingPattern */: + return bindingNameText(ts.cast(ts.first(name.elements), ts.isBindingElement).name); + default: + return ts.Debug.assertNever(name); + } + } function isImportedDeclaration(node) { return node.kind === 244 /* ImportClause */ || node.kind === 247 /* ImportSpecifier */ || node.kind === 245 /* NamespaceImport */; } function importClauseFromImported(decl) { return decl.kind === 244 /* ImportClause */ ? decl : decl.kind === 245 /* NamespaceImport */ ? decl.parent : decl.parent.parent; } - function forEachImportedDeclaration(importClause, cb) { - var defaultName = importClause.name, namedBindings = importClause.namedBindings; - return (defaultName && cb(importClause)) || - namedBindings && (namedBindings.kind === 245 /* NamespaceImport */ ? cb(namedBindings) : ts.forEach(namedBindings.elements, cb)); - } function checkBlock(node) { // Grammar checking for SyntaxKind.Block if (node.kind === 212 /* Block */) { @@ -48509,8 +48537,8 @@ var ts; if (!areTypeParametersIdentical(declarations, type.localTypeParameters)) { // Report an error on every conflicting declaration. var name = symbolToString(symbol); - for (var _i = 0, declarations_5 = declarations; _i < declarations_5.length; _i++) { - var declaration = declarations_5[_i]; + for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { + var declaration = declarations_6[_i]; error(declaration.name, ts.Diagnostics.All_declarations_of_0_must_have_identical_type_parameters, name); } } @@ -48519,8 +48547,8 @@ var ts; function areTypeParametersIdentical(declarations, targetParameters) { var maxTypeArgumentCount = ts.length(targetParameters); var minTypeArgumentCount = getMinTypeArgumentCount(targetParameters); - for (var _i = 0, declarations_6 = declarations; _i < declarations_6.length; _i++) { - var declaration = declarations_6[_i]; + for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { + var declaration = declarations_7[_i]; // If this declaration has too few or too many type parameters, we report an error var sourceParameters = ts.getEffectiveTypeParameterDeclarations(declaration); var numTypeParameters = sourceParameters.length; @@ -49115,8 +49143,8 @@ var ts; } function getFirstNonAmbientClassOrFunctionDeclaration(symbol) { var declarations = symbol.declarations; - for (var _i = 0, declarations_7 = declarations; _i < declarations_7.length; _i++) { - var declaration = declarations_7[_i]; + for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { + var declaration = declarations_8[_i]; if ((declaration.kind === 234 /* ClassDeclaration */ || (declaration.kind === 233 /* FunctionDeclaration */ && ts.nodeIsPresent(declaration.body))) && !(declaration.flags & 4194304 /* Ambient */)) { @@ -49558,8 +49586,8 @@ var ts; return; } if (exportedDeclarationsCount > 1) { - for (var _i = 0, declarations_8 = declarations; _i < declarations_8.length; _i++) { - var declaration = declarations_8[_i]; + for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { + var declaration = declarations_9[_i]; if (isNotOverload(declaration)) { diagnostics.add(ts.createDiagnosticForNode(declaration, ts.Diagnostics.Cannot_redeclare_exported_variable_0, ts.unescapeLeadingUnderscores(id))); } @@ -90998,8 +91026,8 @@ var ts; return undefined; } var scope; - for (var _i = 0, declarations_9 = declarations; _i < declarations_9.length; _i++) { - var declaration = declarations_9[_i]; + for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { + var declaration = declarations_10[_i]; var container = ts.getContainerNode(declaration); if (scope && scope !== container) { // Different declarations have different containers, bail out @@ -91712,8 +91740,8 @@ var ts; // To achieve that we will keep iterating until the result stabilizes. // Remember the last meaning lastIterationMeaning = meaning; - for (var _i = 0, declarations_10 = declarations; _i < declarations_10.length; _i++) { - var declaration = declarations_10[_i]; + for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { + var declaration = declarations_11[_i]; var declarationMeaning = ts.getMeaningFromDeclaration(declaration); if (declarationMeaning & meaning) { meaning |= declarationMeaning; @@ -92784,8 +92812,8 @@ var ts; if (!match) { return; // continue to next named declarations } - for (var _i = 0, declarations_11 = declarations; _i < declarations_11.length; _i++) { - var declaration = declarations_11[_i]; + for (var _i = 0, declarations_12 = declarations; _i < declarations_12.length; _i++) { + var declaration = declarations_12[_i]; if (!shouldKeepItem(declaration, checker)) continue; if (patternMatcher.patternContainsDots) { @@ -95002,8 +95030,8 @@ var ts; } } }; - for (var _b = 0, declarations_12 = declarations; _b < declarations_12.length; _b++) { - var declaration = declarations_12[_b]; + for (var _b = 0, declarations_13 = declarations; _b < declarations_13.length; _b++) { + var declaration = declarations_13[_b]; var state_5 = _loop_16(declaration); if (typeof state_5 === "object") return state_5.value; @@ -101659,20 +101687,26 @@ var ts; ts.Diagnostics.Property_0_is_declared_but_its_value_is_never_read.code, ts.Diagnostics.All_imports_in_import_declaration_are_unused.code, ts.Diagnostics.All_destructured_elements_are_unused.code, + ts.Diagnostics.All_variables_are_unused.code, ]; codefix.registerCodeFix({ errorCodes: errorCodes, getCodeActions: function (context) { var errorCode = context.errorCode, sourceFile = context.sourceFile; - var importDecl = tryGetFullImport(sourceFile, context.span.start); + var startToken = ts.getTokenAtPosition(sourceFile, context.span.start, /*includeJsDocComment*/ false); + var importDecl = tryGetFullImport(startToken); if (importDecl) { var changes = ts.textChanges.ChangeTracker.with(context, function (t) { return t.deleteNode(sourceFile, importDecl); }); return [codefix.createCodeFixAction(fixName, changes, [ts.Diagnostics.Remove_import_from_0, ts.showModuleSpecifier(importDecl)], fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } - var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, context.span.start, /*deleted*/ undefined); }); + var delDestructure = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullDestructure(t, sourceFile, startToken, /*deleted*/ undefined); }); if (delDestructure.length) { return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_destructuring, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; } + var delVar = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteFullVariableStatement(t, sourceFile, startToken, /*deleted*/ undefined); }); + if (delVar.length) { + return [codefix.createCodeFixAction(fixName, delDestructure, ts.Diagnostics.Remove_variable_statement, fixIdDelete, ts.Diagnostics.Delete_all_unused_declarations)]; + } var token = getToken(sourceFile, ts.textSpanEnd(context.span)); var result = []; var deletion = ts.textChanges.ChangeTracker.with(context, function (t) { return tryDeleteDeclaration(t, sourceFile, token, /*deleted*/ undefined); }); @@ -101691,6 +101725,7 @@ var ts; var deleted = new NodeSet(); return codefix.codeFixAll(context, errorCodes, function (changes, diag) { var sourceFile = context.sourceFile; + var startToken = ts.getTokenAtPosition(sourceFile, diag.start, /*includeJsDocComment*/ false); var token = ts.findPrecedingToken(ts.textSpanEnd(diag), diag.file); switch (context.fixId) { case fixIdPrefix: @@ -101702,14 +101737,12 @@ var ts; // Ignore if this range was already deleted. if (deleted.some(function (d) { return ts.rangeContainsPosition(d, diag.start); })) break; - var importDecl = tryGetFullImport(diag.file, diag.start); + var importDecl = tryGetFullImport(startToken); if (importDecl) { changes.deleteNode(sourceFile, importDecl); } - else { - if (!tryDeleteFullDestructure(changes, sourceFile, diag.start, deleted)) { - tryDeleteDeclaration(changes, sourceFile, token, deleted); - } + else if (!tryDeleteFullDestructure(changes, sourceFile, startToken, deleted) && !tryDeleteFullVariableStatement(changes, sourceFile, startToken, deleted)) { + tryDeleteDeclaration(changes, sourceFile, token, deleted); } break; default: @@ -101719,15 +101752,13 @@ var ts; }, }); // Sometimes the diagnostic span is an entire ImportDeclaration, so we should remove the whole thing. - function tryGetFullImport(sourceFile, pos) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + function tryGetFullImport(startToken) { return startToken.kind === 91 /* ImportKeyword */ ? ts.tryCast(startToken.parent, ts.isImportDeclaration) : undefined; } - function tryDeleteFullDestructure(changes, sourceFile, pos, deletedAncestors) { - var startToken = ts.getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false); + function tryDeleteFullDestructure(changes, sourceFile, startToken, deletedAncestors) { if (startToken.kind !== 17 /* OpenBraceToken */ || !ts.isObjectBindingPattern(startToken.parent)) return false; - var decl = startToken.parent.parent; + var decl = ts.cast(startToken.parent, ts.isObjectBindingPattern).parent; switch (decl.kind) { case 231 /* VariableDeclaration */: tryDeleteVariableDeclaration(changes, sourceFile, decl, deletedAncestors); @@ -101747,6 +101778,16 @@ var ts; } return true; } + function tryDeleteFullVariableStatement(changes, sourceFile, startToken, deletedAncestors) { + var declarationList = ts.tryCast(startToken.parent, ts.isVariableDeclarationList); + if (declarationList && declarationList.getChildren(sourceFile)[0] === startToken) { + if (deletedAncestors) + deletedAncestors.add(declarationList); + changes.deleteNode(sourceFile, declarationList.parent.kind === 213 /* VariableStatement */ ? declarationList.parent : declarationList); + return true; + } + return false; + } function getToken(sourceFile, pos) { var token = ts.findPrecedingToken(pos, sourceFile, /*startNode*/ undefined, /*includeJsDoc*/ true); // this handles var ["computed"] = 12; @@ -106517,8 +106558,8 @@ var ts; return ts.emptyArray; var doc = ts.JsDoc.getJsDocCommentsFromDeclarations(declarations); if (doc.length === 0 || declarations.some(hasJSDocInheritDocTag)) { - for (var _i = 0, declarations_13 = declarations; _i < declarations_13.length; _i++) { - var declaration = declarations_13[_i]; + for (var _i = 0, declarations_14 = declarations; _i < declarations_14.length; _i++) { + var declaration = declarations_14[_i]; var inheritedDocs = findInheritedJSDocComments(declaration, declaration.symbol.name, checker); // TODO: GH#16312 Return a ReadonlyArray, avoid copying inheritedDocs if (inheritedDocs) diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index 40574ab68d5..23bca5d1167 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -4532,6 +4532,7 @@ var ts; _0_is_declared_but_never_used: diag(6196, ts.DiagnosticCategory.Error, "_0_is_declared_but_never_used_6196", "'{0}' is declared but never used.", true), Include_modules_imported_with_json_extension: diag(6197, ts.DiagnosticCategory.Message, "Include_modules_imported_with_json_extension_6197", "Include modules imported with '.json' extension"), All_destructured_elements_are_unused: diag(6198, ts.DiagnosticCategory.Error, "All_destructured_elements_are_unused_6198", "All destructured elements are unused.", true), + All_variables_are_unused: diag(6199, ts.DiagnosticCategory.Error, "All_variables_are_unused_6199", "All variables are unused.", true), Projects_to_reference: diag(6300, ts.DiagnosticCategory.Message, "Projects_to_reference_6300", "Projects to reference"), Enable_project_compilation: diag(6302, ts.DiagnosticCategory.Message, "Enable_project_compilation_6302", "Enable project compilation"), Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0: diag(6202, ts.DiagnosticCategory.Error, "Project_references_may_not_form_a_circular_graph_Cycle_detected_Colon_0_6202", "Project references may not form a circular graph. Cycle detected: {0}"), @@ -4640,6 +4641,7 @@ var ts; Implement_inherited_abstract_class: diag(90007, ts.DiagnosticCategory.Message, "Implement_inherited_abstract_class_90007", "Implement inherited abstract class"), Add_0_to_unresolved_variable: diag(90008, ts.DiagnosticCategory.Message, "Add_0_to_unresolved_variable_90008", "Add '{0}.' to unresolved variable"), Remove_destructuring: diag(90009, ts.DiagnosticCategory.Message, "Remove_destructuring_90009", "Remove destructuring"), + Remove_variable_statement: diag(90010, ts.DiagnosticCategory.Message, "Remove_variable_statement_90010", "Remove variable statement"), Import_0_from_module_1: diag(90013, ts.DiagnosticCategory.Message, "Import_0_from_module_1_90013", "Import '{0}' from module \"{1}\""), Change_0_to_1: diag(90014, ts.DiagnosticCategory.Message, "Change_0_to_1_90014", "Change '{0}' to '{1}'"), Add_0_to_existing_import_declaration_from_1: diag(90015, ts.DiagnosticCategory.Message, "Add_0_to_existing_import_declaration_from_1_90015", "Add '{0}' to existing import declaration from \"{1}\""),