diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e9977c9cd4..cb0016c949 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9191,9 +9191,6 @@ namespace ts { return; } - // Abstract methods can't have an implementation -- in particular, they don't need one. - if (node.flags & NodeFlags.Abstract) { return; } - let seen = false; let subsequentNode = forEachChild(node.parent, c => { if (seen) { @@ -9226,7 +9223,13 @@ namespace ts { error(errorNode, Diagnostics.Constructor_implementation_is_missing); } else { - error(errorNode, Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration); + // Report different errors regarding non-consecutive blocks of declarations depending on whether + // the node in question is abstract. + if (node.flags & NodeFlags.Abstract) { + error(errorNode, Diagnostics.All_declarations_of_an_abstract_member_function_must_be_consecutive); + } else { + error(errorNode, Diagnostics.Function_implementation_is_missing_or_not_immediately_following_the_declaration); + } } } @@ -9303,7 +9306,8 @@ namespace ts { }); } - if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body) { + // Abstract methods can't have an implementation -- in particular, they don't need one. + if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) ) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index a29aed6615..e89a4e03c0 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -398,6 +398,7 @@ namespace ts { Abstract_member_function_0_on_type_1_cannot_be_called_via_super_expression: { code: 2513, category: DiagnosticCategory.Error, key: "Abstract member function '{0}' on type '{1}' cannot be called via super expression." }, Classes_containing_abstract_functions_must_be_marked_abstract: { code: 2514, category: DiagnosticCategory.Error, key: "Classes containing abstract functions must be marked abstract." }, Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_2: { code: 2515, category: DiagnosticCategory.Error, key: "Non-abstract class '{0}' does not implement inherited abstract member '{1}.{2}'." }, + All_declarations_of_an_abstract_member_function_must_be_consecutive: { code: 2516, category: DiagnosticCategory.Error, key: "All declarations of an abstract member function must be consecutive." }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 859565c181..10ff7cbae3 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1579,6 +1579,10 @@ "category": "Error", "code": 2515 }, + "All declarations of an abstract member function must be consecutive.": { + "category": "Error", + "code": 2516 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error", "code": 4000