Skip to content

Commit 92ac406

Browse files
committed
also check that super calls are the first statement within their constructor when compiling them
1 parent a749af9 commit 92ac406

File tree

4 files changed

+19
-1
lines changed

4 files changed

+19
-1
lines changed

src/ast.ts

+8
Original file line numberDiff line numberDiff line change
@@ -1824,6 +1824,14 @@ export class FunctionDeclaration extends DeclarationStatement {
18241824
var typeParameters = this.typeParameters;
18251825
return typeParameters != null && typeParameters.length > 0;
18261826
}
1827+
1828+
get firstStatement(): Statement | null {
1829+
var body = this.body;
1830+
if (!(body && body.kind == NodeKind.BLOCK)) return null;
1831+
var statements = (<BlockStatement>body).statements;
1832+
if (statements.length < 0) return null;
1833+
return statements[0];
1834+
}
18271835
}
18281836

18291837
/** Represents an `if` statement. */

src/compiler.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -5244,7 +5244,14 @@ export class Compiler extends DiagnosticEmitter {
52445244

52455245
// call to `super()`
52465246
case ElementKind.CLASS: {
5247-
if (expression.expression.kind == NodeKind.SUPER) {
5247+
if (expression.expression.kind == NodeKind.SUPER && currentFunction.is(CommonFlags.CONSTRUCTOR)) {
5248+
if (expression.parent != currentFunction.prototype.declaration.firstStatement) {
5249+
this.error(
5250+
DiagnosticCode.A_super_call_must_be_the_first_statement_in_the_constructor,
5251+
expression.range
5252+
);
5253+
return module.createUnreachable();
5254+
}
52485255
let classInstance = assert(currentFunction.parent);
52495256
assert(classInstance.kind == ElementKind.CLASS);
52505257
let expr = this.compileSuperInstantiate(<Class>classInstance, expression.arguments, expression);

src/diagnosticMessages.generated.ts

+2
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ export enum DiagnosticCode {
101101
The_operand_of_an_increment_or_decrement_operator_must_be_a_variable_or_a_property_access = 2357,
102102
The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access = 2364,
103103
Operator_0_cannot_be_applied_to_types_1_and_2 = 2365,
104+
A_super_call_must_be_the_first_statement_in_the_constructor = 2376,
104105
Constructors_for_derived_classes_must_call_super_first = 2377,
105106
_get_and_set_accessor_must_have_the_same_type = 2380,
106107
Constructor_implementation_is_missing = 2390,
@@ -225,6 +226,7 @@ export function diagnosticCodeToString(code: DiagnosticCode): string {
225226
case 2357: return "The operand of an increment or decrement operator must be a variable or a property access.";
226227
case 2364: return "The left-hand side of an assignment expression must be a variable or a property access.";
227228
case 2365: return "Operator '{0}' cannot be applied to types '{1}' and '{2}'.";
229+
case 2376: return "A 'super' call must be the first statement in the constructor.";
228230
case 2377: return "Constructors for derived classes must call 'super' first.";
229231
case 2380: return "'get' and 'set' accessor must have the same type.";
230232
case 2390: return "Constructor implementation is missing.";

src/diagnosticMessages.json

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
"The operand of an increment or decrement operator must be a variable or a property access.": 2357,
9696
"The left-hand side of an assignment expression must be a variable or a property access.": 2364,
9797
"Operator '{0}' cannot be applied to types '{1}' and '{2}'.": 2365,
98+
"A 'super' call must be the first statement in the constructor.": 2376,
9899
"Constructors for derived classes must call 'super' first.": 2377,
99100
"'get' and 'set' accessor must have the same type.": 2380,
100101
"Constructor implementation is missing.": 2390,

0 commit comments

Comments
 (0)