Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allowed non-this, non-super code before super call in derived classes with property initializers #29374

Merged
merged 61 commits into from Jan 14, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
6845db9
Allowed non-this, non-super code before super call in derived classes
Jan 11, 2019
dbd3a2a
Used new isNewThisScope utility and dummy prop in baselines
Jan 11, 2019
5aa79cd
Accounted for parameters and get/set accessor bodies
Jan 11, 2019
02516cc
Accounted for class extensions
Jan 12, 2019
00b4a2b
(node|statement)RefersToSuperOrThis wasn't checking root level scope …
Jan 12, 2019
6d06b21
Better 'references' name and comments; accounted for more method edge…
Jan 13, 2019
ccd52fc
Limited super calls to root-level statements in constructor bodies
Jan 15, 2019
da71ed9
Merge branch 'master'
Jan 15, 2019
b4a9ac2
Fixed error number following 'master' merge
Jan 15, 2019
0d91548
Added decorator test cases
Jan 21, 2019
e4dca14
Again allowed arrow functions
Jan 21, 2019
c8fc681
Merge branch 'master'
Jul 16, 2019
cf52812
Accepted new baselines
Jul 16, 2019
a39761d
Added allowance for (super())
Jul 19, 2019
afc58e1
Reworked emitter transforms for ES this binding semantics
Sep 2, 2019
a48d1ea
Used skipOuterExpressions when diving for super()s; fix prop ordering
Sep 2, 2019
efbe416
Allow direct var _this = super() when no pre-super() statements; lint…
Sep 2, 2019
429347d
Always with the TSLint
Sep 2, 2019
03da7f7
One last touchup: skipOuterExpressions in es2015 transformer
Sep 2, 2019
142704e
Merge branch 'master'
Oct 21, 2019
e71bee1
Fixed new lint complaint in utilities.ts
Oct 21, 2019
4cef299
Again added a falls-through; it'd be swell if I could run linting loc…
Oct 21, 2019
660feb2
This time I think I got it
Oct 21, 2019
e425e9b
Well at least the error is a different one
Oct 21, 2019
041c58a
Merge branch 'master'
JoshuaKGoldberg Feb 15, 2020
74e6972
Undid irrelevant whitespace changes
JoshuaKGoldberg Feb 16, 2020
093b1b7
Mostly addressed private/field issues
JoshuaKGoldberg Feb 28, 2020
7d99293
Merge branch 'master' of https://github.com/microsoft/TypeScript into…
orta Mar 3, 2020
c09a156
Accepted derivedClassSuperProperties baseline
JoshuaKGoldberg Mar 4, 2020
25c5c10
Merge branch 'master'
JoshuaKGoldberg Mar 5, 2020
39207d2
Lint fix, lovely
JoshuaKGoldberg Mar 5, 2020
25aff6c
Remove now-unnecesary comment
JoshuaKGoldberg Mar 6, 2020
f33707f
Merge branch 'master'
Dec 2, 2020
34ad5b3
First round of feedback
Dec 2, 2020
9022a17
Moved prologue statements to start of statements
Dec 2, 2020
cd82cc5
Added consideration for super statements in loops and the like
Dec 2, 2020
2629491
Ordering and a _this_1 test
Dec 2, 2020
8039315
Missed the one change I needed...
Dec 2, 2020
eb7388a
Merge branch 'master'
JoshuaKGoldberg Jan 8, 2021
39ffad6
First round of feedback corrections
JoshuaKGoldberg Jan 11, 2021
26fc18c
Feedback round two: statements
JoshuaKGoldberg Jan 11, 2021
0448f54
Feedback: used more direct statements
JoshuaKGoldberg Jan 11, 2021
70e741b
Fixed classFields emit to not duplicate temp variables
JoshuaKGoldberg Jan 11, 2021
d5ad9c3
Refactored es2015 helper to be less overloaded
JoshuaKGoldberg Jan 11, 2021
fe2ac08
Accounted for parentheses
JoshuaKGoldberg Jan 11, 2021
360ad2e
Simpler feedback: -1, and emptyArray
JoshuaKGoldberg Jan 11, 2021
23780a1
Next feedback: superStatementIndex
JoshuaKGoldberg Jan 11, 2021
4b0bd82
Feedback: simplified to no longer create slice arrays
JoshuaKGoldberg Jan 12, 2021
6319af5
Adjusted for default and rest parameters
Jan 14, 2021
e434962
Added test case for commas
Jan 14, 2021
bacc434
Corrected comment ranges
Jan 21, 2021
b250f5f
Merge branch 'master' into non-this-super-before-super
rbuckton Jan 25, 2021
44d7a9a
Handled comments after super, with tests
Jan 27, 2021
f16ccd4
Merge branch 'master'
Jan 27, 2021
44a164e
Merge branch 'master'
JoshuaKGoldberg Feb 24, 2021
af16920
Merge branch 'master'
May 28, 2021
47fc125
Merge branch 'main'
Sep 11, 2021
ffdc7f8
Merge branch 'main'
Oct 18, 2021
dea7150
Merge branch 'main'
JoshuaKGoldberg Jan 13, 2022
39d9901
Fixed Bad/Late super baselines
JoshuaKGoldberg Jan 13, 2022
1b3dd6d
Remove unused param and unnecessary baseline comments
Jan 13, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 14 additions & 2 deletions src/compiler/checker.ts
Expand Up @@ -23613,12 +23613,12 @@ namespace ts {
superCallStatement = <ExpressionStatement>statement;
break;
}
if (!isPrologueDirective(statement)) {
if (!isPrologueDirective(statement) && nodeReferencesSuperOrThis(statement)) {
break;
}
}
if (!superCallStatement) {
error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_when_a_class_contains_initialized_properties_or_has_parameter_properties);
error(node, Diagnostics.A_super_call_must_be_the_first_statement_in_the_constructor_to_refer_to_super_or_this_when_a_derived_class_contains_initialized_properties_or_has_parameter_properties);
}
}
}
Expand All @@ -23628,6 +23628,18 @@ namespace ts {
}
}

function nodeReferencesSuperOrThis(node: Statement): boolean {
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
if (node.kind === SyntaxKind.SuperKeyword || node.kind === SyntaxKind.ThisKeyword) {
return true;
}

if (isNewThisScope(node)) {
return false;
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
}

return !!forEachChild(node, nodeReferencesSuperOrThis);
}

function checkAccessorDeclaration(node: AccessorDeclaration) {
if (produceDiagnostics) {
// Grammar checking accessors
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/diagnosticMessages.json
Expand Up @@ -1328,7 +1328,7 @@
"category": "Error",
"code": 2375
},
"A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.": {
"A 'super' call must be the first statement in the constructor to refer to 'super' or 'this' when a derived class contains initialized properties or has parameter properties.": {
"category": "Error",
"code": 2376
},
Expand Down
27 changes: 27 additions & 0 deletions src/compiler/utilities.ts
Expand Up @@ -6258,6 +6258,33 @@ namespace ts {
return isSourceFile(node) || isModuleBlock(node) || isBlock(node) && isFunctionLike(node.parent);
}

/**
* @returns Whether a node or its children refer to a different `this` than its parent.
* @internal
*/
export function isNewThisScope(node: Node): boolean {
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
switch (node.kind) {
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
case SyntaxKind.PropertyDeclaration:
return true;
case SyntaxKind.Block:
switch (node.parent.kind) {
// The `extends` clause of a class is its parent scope, unlike its constructor and methods
case SyntaxKind.Constructor:
case SyntaxKind.MethodDeclaration:
// Object properties can have computed names; only method-like bodies start a new scope
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
return true;
default:
return false;
}
default:
return false;
}
}

// Classes
export function isClassElement(node: Node): node is ClassElement {
const kind = node.kind;
Expand Down
14 changes: 1 addition & 13 deletions tests/baselines/reference/classUpdateTests.errors.txt
@@ -1,11 +1,9 @@
tests/cases/compiler/classUpdateTests.ts(34,2): error TS2377: Constructors for derived classes must contain a 'super' call.
tests/cases/compiler/classUpdateTests.ts(43,18): error TS2335: 'super' can only be referenced in a derived class.
tests/cases/compiler/classUpdateTests.ts(57,2): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
tests/cases/compiler/classUpdateTests.ts(63,7): error TS2415: Class 'L' incorrectly extends base class 'G'.
Property 'p1' is private in type 'L' but not in type 'G'.
tests/cases/compiler/classUpdateTests.ts(69,7): error TS2415: Class 'M' incorrectly extends base class 'G'.
Property 'p1' is private in type 'M' but not in type 'G'.
tests/cases/compiler/classUpdateTests.ts(70,2): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
tests/cases/compiler/classUpdateTests.ts(93,3): error TS1128: Declaration or statement expected.
tests/cases/compiler/classUpdateTests.ts(95,1): error TS1128: Declaration or statement expected.
tests/cases/compiler/classUpdateTests.ts(99,3): error TS1128: Declaration or statement expected.
Expand All @@ -18,7 +16,7 @@ tests/cases/compiler/classUpdateTests.ts(111,15): error TS1005: ';' expected.
tests/cases/compiler/classUpdateTests.ts(113,1): error TS1128: Declaration or statement expected.


==== tests/cases/compiler/classUpdateTests.ts (16 errors) ====
==== tests/cases/compiler/classUpdateTests.ts (14 errors) ====
//
// test codegen for instance properties
//
Expand Down Expand Up @@ -80,14 +78,9 @@ tests/cases/compiler/classUpdateTests.ts(113,1): error TS1128: Declaration or st

class K extends G {
constructor(public p1:number) { // ERROR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var i = 0;
~~~~~~~~~~~~
super();
~~~~~~~~~~
}
~~
!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
}

class L extends G {
Expand All @@ -104,14 +97,9 @@ tests/cases/compiler/classUpdateTests.ts(113,1): error TS1128: Declaration or st
!!! error TS2415: Class 'M' incorrectly extends base class 'G'.
!!! error TS2415: Property 'p1' is private in type 'M' but not in type 'G'.
constructor(private p1:number) { // ERROR
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var i = 0;
~~~~~~~~~~~~
super();
~~~~~~~~~~
}
~~
!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
}

//
Expand Down
@@ -1,15 +1,13 @@
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(15,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(30,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(47,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(56,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(56,5): error TS2376: A 'super' call must be the first statement in the constructor to refer to 'super' or 'this' when a derived class contains initialized properties or has parameter properties.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(57,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(58,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(79,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(79,5): error TS2376: A 'super' call must be the first statement in the constructor to refer to 'super' or 'this' when a derived class contains initialized properties or has parameter properties.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(80,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.
tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts(81,9): error TS17009: 'super' must be called before accessing 'this' in the constructor of a derived class.


==== tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts (9 errors) ====
==== tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassParameterProperties.ts (7 errors) ====
// ordering of super calls in derived constructors matters depending on other class contents

class Base {
Expand All @@ -25,14 +23,9 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP

class Derived2 extends Base {
constructor(public y: string) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var a = 1;
~~~~~~~~~~~~~~~~~~
super(); // error
~~~~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
}

class Derived3 extends Base {
Expand All @@ -45,14 +38,9 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP
class Derived4 extends Base {
a = 1;
constructor(y: string) {
~~~~~~~~~~~~~~~~~~~~~~~~
var b = 2;
~~~~~~~~~~~~~~~~~~
super(); // error
~~~~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
}

class Derived5 extends Base {
Expand Down Expand Up @@ -91,7 +79,7 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP
~~~~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
!!! error TS2376: A 'super' call must be the first statement in the constructor to refer to 'super' or 'this' when a derived class contains initialized properties or has parameter properties.
}

class Derived8 extends Base {
Expand Down Expand Up @@ -124,7 +112,7 @@ tests/cases/conformance/classes/constructorDeclarations/superCalls/derivedClassP
~~~~~~~~~~~~~~~~~~~~~~~~~
}
~~~~~
!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
!!! error TS2376: A 'super' call must be the first statement in the constructor to refer to 'super' or 'this' when a derived class contains initialized properties or has parameter properties.
}

class Derived10<T> extends Base2<T> {
Expand Down