@@ -7083,6 +7083,7 @@ namespace ts {
7083
7083
...!length(baseTypes) ? [] : [factory.createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))],
7084
7084
...!length(implementsExpressions) ? [] : [factory.createHeritageClause(SyntaxKind.ImplementsKeyword, implementsExpressions)]
7085
7085
];
7086
+ const modifiers = originalDecl && hasEffectiveModifier(originalDecl, ModifierFlags.Abstract) ? factory.createModifiersFromModifierFlags(ModifierFlags.Abstract) : undefined;
7086
7087
const symbolProps = getNonInterhitedProperties(classType, baseTypes, getPropertiesOfType(classType));
7087
7088
const publicSymbolProps = filter(symbolProps, s => {
7088
7089
// `valueDeclaration` could be undefined if inherited from
@@ -7129,7 +7130,7 @@ namespace ts {
7129
7130
context.enclosingDeclaration = oldEnclosing;
7130
7131
addResult(setTextRange(factory.createClassDeclaration(
7131
7132
/*decorators*/ undefined,
7132
- /* modifiers*/ undefined ,
7133
+ modifiers,
7133
7134
localName,
7134
7135
typeParamDecls,
7135
7136
heritageClauses,
@@ -7470,20 +7471,11 @@ namespace ts {
7470
7471
initializer: Expression | undefined
7471
7472
) => T, methodKind: SignatureDeclaration["kind"], useAccessors: boolean): (p: Symbol, isStatic: boolean, baseType: Type | undefined) => (T | AccessorDeclaration | (T | AccessorDeclaration)[]) {
7472
7473
return function serializePropertySymbol(p: Symbol, isStatic: boolean, baseType: Type | undefined): (T | AccessorDeclaration | (T | AccessorDeclaration)[]) {
7473
- const modifierFlags = getDeclarationModifierFlagsFromSymbol(p);
7474
- const isPrivate = !!(modifierFlags & ModifierFlags.Private);
7475
- if (isStatic && (p.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias))) {
7476
- // Only value-only-meaning symbols can be correctly encoded as class statics, type/namespace/alias meaning symbols
7477
- // need to be merged namespace members
7478
- return [];
7479
- }
7480
- if (p.flags & SymbolFlags.Prototype ||
7481
- (baseType && getPropertyOfType(baseType, p.escapedName)
7482
- && isReadonlySymbol(getPropertyOfType(baseType, p.escapedName)!) === isReadonlySymbol(p)
7483
- && (p.flags & SymbolFlags.Optional) === (getPropertyOfType(baseType, p.escapedName)!.flags & SymbolFlags.Optional)
7484
- && isTypeIdenticalTo(getTypeOfSymbol(p), getTypeOfPropertyOfType(baseType, p.escapedName)!))) {
7474
+ if (isOmittedSerializationProperty(p, isStatic, baseType)) {
7485
7475
return [];
7486
7476
}
7477
+ const modifierFlags = getDeclarationModifierFlagsFromSymbol(p);
7478
+ const isPrivate = !!(modifierFlags & ModifierFlags.Private);
7487
7479
const flag = (modifierFlags & ~ModifierFlags.Async) | (isStatic ? ModifierFlags.Static : 0);
7488
7480
const name = getPropertyNameNodeForSymbol(p, context);
7489
7481
const firstPropertyLikeDecl = p.declarations?.find(or(isPropertyDeclaration, isAccessor, isVariableDeclaration, isPropertySignature, isBinaryExpression, isPropertyAccessExpression));
@@ -7569,6 +7561,29 @@ namespace ts {
7569
7561
};
7570
7562
}
7571
7563
7564
+ function isOmittedSerializationProperty(prop: Symbol, isStatic: boolean, type: Type | undefined) {
7565
+ // Only value-only-meaning symbols can be correctly encoded as class statics, type/namespace/alias meaning symbols
7566
+ // need to be merged namespace members
7567
+ if (isStatic && (prop.flags & (SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias)) || (prop.flags & SymbolFlags.Prototype)) {
7568
+ return true;
7569
+ }
7570
+ if (type) {
7571
+ const baseProp = getPropertyOfType(type, prop.escapedName);
7572
+ const basePropType = getTypeOfPropertyOfType(type, prop.escapedName);
7573
+ if (baseProp && basePropType) {
7574
+ if (getDeclarationModifierFlagsFromSymbol(baseProp) & ModifierFlags.Abstract) {
7575
+ return prop === baseProp;
7576
+ }
7577
+ return (
7578
+ (prop.flags & SymbolFlags.Optional) === (baseProp.flags & SymbolFlags.Optional) &&
7579
+ isReadonlySymbol(baseProp) === isReadonlySymbol(prop) &&
7580
+ isTypeIdenticalTo(getTypeOfSymbol(prop), basePropType)
7581
+ );
7582
+ }
7583
+ }
7584
+ return false;
7585
+ }
7586
+
7572
7587
function serializePropertySymbolForInterface(p: Symbol, baseType: Type | undefined) {
7573
7588
return serializePropertySymbolForInterfaceWorker(p, /*isStatic*/ false, baseType);
7574
7589
}
@@ -29639,7 +29654,7 @@ namespace ts {
29639
29654
return resolveErrorCall(node);
29640
29655
}
29641
29656
const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol);
29642
- if (valueDecl && hasSyntacticModifier (valueDecl, ModifierFlags.Abstract)) {
29657
+ if (valueDecl && hasEffectiveModifier (valueDecl, ModifierFlags.Abstract)) {
29643
29658
error(node, Diagnostics.Cannot_create_an_instance_of_an_abstract_class);
29644
29659
return resolveErrorCall(node);
29645
29660
}
@@ -31180,7 +31195,7 @@ namespace ts {
31180
31195
if (type && type.flags & TypeFlags.Never) {
31181
31196
error(errorNode, Diagnostics.A_function_returning_never_cannot_have_a_reachable_end_point);
31182
31197
}
31183
- else if (type && !hasExplicitReturn) {
31198
+ else if (type && !hasExplicitReturn && !hasEffectiveModifier(func, ModifierFlags.Abstract) ) {
31184
31199
// minimal check: function has syntactic return type annotation and no explicit return statements in the body
31185
31200
// this function does not conform to the specification.
31186
31201
error(errorNode, Diagnostics.A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value);
@@ -33645,8 +33660,9 @@ namespace ts {
33645
33660
// Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
33646
33661
checkFunctionOrMethodDeclaration(node);
33647
33662
33648
- // method signatures already report "implementation not allowed in ambient context" elsewhere
33649
- if (hasSyntacticModifier(node, ModifierFlags.Abstract) && node.kind === SyntaxKind.MethodDeclaration && node.body) {
33663
+ // Abstract methods cannot have an implementation.
33664
+ // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node.
33665
+ if (isMethodDeclaration(node) && hasAbstractDeclarationBody(node)) {
33650
33666
error(node, Diagnostics.Method_0_cannot_have_an_implementation_because_it_is_marked_abstract, declarationNameToString(node.name));
33651
33667
}
33652
33668
@@ -33775,7 +33791,7 @@ namespace ts {
33775
33791
checkSignatureDeclaration(node);
33776
33792
if (node.kind === SyntaxKind.GetAccessor) {
33777
33793
if (!(node.flags & NodeFlags.Ambient) && nodeIsPresent(node.body) && (node.flags & NodeFlags.HasImplicitReturn)) {
33778
- if (!(node.flags & NodeFlags.HasExplicitReturn)) {
33794
+ if (!(node.flags & NodeFlags.HasExplicitReturn) && !(isInJSFile(node) && hasEffectiveModifier(node, ModifierFlags.Abstract)) ) {
33779
33795
error(node.name, Diagnostics.A_get_accessor_must_return_a_value);
33780
33796
}
33781
33797
}
@@ -37766,7 +37782,7 @@ namespace ts {
37766
37782
// It is an error to inherit an abstract member without implementing it or being declared abstract.
37767
37783
// If there is no declaration for the derived class (as in the case of class expressions),
37768
37784
// then the class cannot be declared abstract.
37769
- if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !hasSyntacticModifier (derivedClassDecl, ModifierFlags.Abstract))) {
37785
+ if (baseDeclarationFlags & ModifierFlags.Abstract && (!derivedClassDecl || !hasEffectiveModifier (derivedClassDecl, ModifierFlags.Abstract))) {
37770
37786
// Searches other base types for a declaration that would satisfy the inherited abstract member.
37771
37787
// (The class may have more than one base type via declaration merging with an interface with the
37772
37788
// same name.)
@@ -37874,7 +37890,7 @@ namespace ts {
37874
37890
const properties = getPropertiesOfType(getTypeWithThisArgument(base, type.thisType));
37875
37891
for (const prop of properties) {
37876
37892
const existing = seen.get(prop.escapedName);
37877
- if (existing && !isPropertyIdenticalTo(existing, prop)) {
37893
+ if (existing && !isPropertyIdenticalTo(existing, prop) && !(getDeclarationModifierFlagsFromSymbol(prop) & ModifierFlags.Abstract) ) {
37878
37894
seen.delete(prop.escapedName);
37879
37895
}
37880
37896
}
@@ -42004,13 +42020,11 @@ namespace ts {
42004
42020
return grammarErrorAtPos(accessor, accessor.end - 1, ";".length, Diagnostics._0_expected, "{");
42005
42021
}
42006
42022
}
42007
- if (accessor.body) {
42008
- if (hasSyntacticModifier(accessor, ModifierFlags.Abstract)) {
42009
- return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation);
42010
- }
42011
- if (accessor.parent.kind === SyntaxKind.TypeLiteral || accessor.parent.kind === SyntaxKind.InterfaceDeclaration) {
42012
- return grammarErrorOnNode(accessor.body, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
42013
- }
42023
+ if (hasAbstractDeclarationBody(accessor)) {
42024
+ return grammarErrorOnNode(accessor, Diagnostics.An_abstract_accessor_cannot_have_an_implementation);
42025
+ }
42026
+ if (accessor.body && (accessor.parent.kind === SyntaxKind.TypeLiteral || accessor.parent.kind === SyntaxKind.InterfaceDeclaration)) {
42027
+ return grammarErrorOnNode(accessor.body, Diagnostics.An_implementation_cannot_be_declared_in_ambient_contexts);
42014
42028
}
42015
42029
if (accessor.typeParameters) {
42016
42030
return grammarErrorOnNode(accessor.name, Diagnostics.An_accessor_cannot_have_type_parameters);
@@ -42039,6 +42053,23 @@ namespace ts {
42039
42053
return false;
42040
42054
}
42041
42055
42056
+ function hasAbstractDeclarationBody(node: MethodDeclaration | AccessorDeclaration) {
42057
+ if (hasEffectiveModifier(node, ModifierFlags.Abstract) && node.body) {
42058
+ if (isInJSFile(node)) {
42059
+ const statement = singleOrUndefined(node.body.statements);
42060
+ if (statement && isThrowStatement(statement)) {
42061
+ return false;
42062
+ }
42063
+ const returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(node));
42064
+ if (returnType === neverType) {
42065
+ return false;
42066
+ }
42067
+ return !!length(node.body.statements);
42068
+ }
42069
+ return true;
42070
+ }
42071
+ }
42072
+
42042
42073
/** Does the accessor have the right number of parameters?
42043
42074
* A get accessor has no parameters or a single `this` parameter.
42044
42075
* A set accessor has one parameter or a `this` parameter and one more parameter.
0 commit comments