Skip to content

Commit c1d23c7

Browse files
authored
Merge branch 'main' into main
2 parents 8305d70 + 9d36497 commit c1d23c7

19 files changed

+652
-30
lines changed

.devcontainer/devcontainer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
// Use 'postCreateCommand' to run commands after the container is created.
1717
"postCreateCommand": {
18-
"Configure Build Tools": "sudo corepack enable npm; sudo npm install -g hereby; npm ci",
18+
"Configure Build Tools": "sudo npm install -g hereby; npm ci",
1919
"Install pprof": "go install github.com/google/pprof@latest",
2020
"Install Graphviz": "sudo apt install graphviz"
2121
},

src/compiler/checker.ts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ import {
383383
getTextOfPropertyName,
384384
getThisContainer,
385385
getThisParameter,
386+
getTokenPosOfNode,
386387
getTrailingSemicolonDeferringWriter,
387388
getTypeParameterFromJsDoc,
388389
getUseDefineForClassFields,
@@ -13211,6 +13212,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1321113212
}
1321213213

1321313214
function getBaseTypes(type: InterfaceType): BaseType[] {
13215+
if (!(getObjectFlags(type) & (ObjectFlags.ClassOrInterface | ObjectFlags.Reference))) {
13216+
return emptyArray;
13217+
}
1321413218
if (!type.baseTypesResolved) {
1321513219
if (pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseTypes)) {
1321613220
if (type.objectFlags & ObjectFlags.Tuple) {
@@ -34448,10 +34452,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3444834452
(flags & ModifierFlags.Abstract) && symbolHasNonMethodDeclaration(prop) &&
3444934453
(isThisProperty(location) || isThisInitializedObjectBindingExpression(location) || isObjectBindingPattern(location.parent) && isThisInitializedDeclaration(location.parent.parent))
3445034454
) {
34451-
const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop)!);
34452-
if (declaringClassDeclaration && isNodeUsedDuringClassInitialization(location)) {
34455+
const parentSymbol = getParentOfSymbol(prop);
34456+
if (parentSymbol && parentSymbol.flags & SymbolFlags.Class && isNodeUsedDuringClassInitialization(location)) {
3445334457
if (errorNode) {
34454-
error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name!));
34458+
error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), symbolToString(parentSymbol));
3445534459
}
3445634460
return false;
3445734461
}
@@ -35052,28 +35056,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3505235056
* In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration.
3505335057
*/
3505435058
function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean {
35055-
if (!(prop.parent!.flags & SymbolFlags.Class)) {
35056-
return false;
35057-
}
35058-
let classType: InterfaceType | undefined = getTypeOfSymbol(prop.parent!) as InterfaceType;
35059-
while (true) {
35060-
classType = classType.symbol && getSuperClass(classType) as InterfaceType | undefined;
35061-
if (!classType) {
35062-
return false;
35063-
}
35064-
const superProperty = getPropertyOfType(classType, prop.escapedName);
35065-
if (superProperty && superProperty.valueDeclaration) {
35066-
return true;
35059+
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
35060+
const baseTypes = getBaseTypes(getDeclaredTypeOfSymbol(prop.parent) as InterfaceType);
35061+
if (baseTypes.length) {
35062+
const superProperty = getPropertyOfType(baseTypes[0], prop.escapedName);
35063+
return !!(superProperty && superProperty.valueDeclaration);
3506735064
}
3506835065
}
35069-
}
35070-
35071-
function getSuperClass(classType: InterfaceType): Type | undefined {
35072-
const x = getBaseTypes(classType);
35073-
if (x.length === 0) {
35074-
return undefined;
35075-
}
35076-
return getIntersectionType(x);
35066+
return false;
3507735067
}
3507835068

3507935069
function reportNonexistentProperty(propNode: Identifier | PrivateIdentifier, containingType: Type, isUncheckedJS: boolean) {
@@ -49232,8 +49222,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4923249222

4923349223
const sourceFile = getSourceFileOfNode(node);
4923449224

49235-
let start = node.pos;
49236-
let end = node.end;
49225+
let startNode = node;
49226+
let endNode = node;
4923749227

4923849228
const parent = node.parent;
4923949229
if (canHaveStatements(parent)) {
@@ -49263,13 +49253,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4926349253
reportedUnreachableNodes.add(nextNode);
4926449254
}
4926549255

49266-
start = statements[first].pos;
49267-
end = statements[last].end;
49256+
startNode = statements[first];
49257+
endNode = statements[last];
4926849258
}
4926949259
}
4927049260

49271-
start = skipTrivia(sourceFile.text, start);
49272-
addErrorOrSuggestion(compilerOptions.allowUnreachableCode === false, createFileDiagnostic(sourceFile, start, end - start, Diagnostics.Unreachable_code_detected));
49261+
const start = getTokenPosOfNode(startNode, sourceFile);
49262+
addErrorOrSuggestion(compilerOptions.allowUnreachableCode === false, createFileDiagnostic(sourceFile, start, endNode.end - start, Diagnostics.Unreachable_code_detected));
4927349263

4927449264
return true;
4927549265
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
checkInheritedProperty.ts(7,14): error TS2729: Property 'b' is used before its initialization.
2+
3+
4+
==== checkInheritedProperty.ts (1 errors) ====
5+
class Base {
6+
}
7+
8+
declare const BaseFactory: new() => Base & { c: string }
9+
10+
class Derived extends BaseFactory {
11+
a = this.b
12+
~
13+
!!! error TS2729: Property 'b' is used before its initialization.
14+
!!! related TS2728 checkInheritedProperty.ts:8:5: 'b' is declared here.
15+
b = "abc"
16+
}
17+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//// [tests/cases/compiler/checkInheritedProperty.ts] ////
2+
3+
=== checkInheritedProperty.ts ===
4+
class Base {
5+
>Base : Symbol(Base, Decl(checkInheritedProperty.ts, 0, 0))
6+
}
7+
8+
declare const BaseFactory: new() => Base & { c: string }
9+
>BaseFactory : Symbol(BaseFactory, Decl(checkInheritedProperty.ts, 3, 13))
10+
>Base : Symbol(Base, Decl(checkInheritedProperty.ts, 0, 0))
11+
>c : Symbol(c, Decl(checkInheritedProperty.ts, 3, 44))
12+
13+
class Derived extends BaseFactory {
14+
>Derived : Symbol(Derived, Decl(checkInheritedProperty.ts, 3, 56))
15+
>BaseFactory : Symbol(BaseFactory, Decl(checkInheritedProperty.ts, 3, 13))
16+
17+
a = this.b
18+
>a : Symbol(Derived.a, Decl(checkInheritedProperty.ts, 5, 35))
19+
>this.b : Symbol(Derived.b, Decl(checkInheritedProperty.ts, 6, 14))
20+
>this : Symbol(Derived, Decl(checkInheritedProperty.ts, 3, 56))
21+
>b : Symbol(Derived.b, Decl(checkInheritedProperty.ts, 6, 14))
22+
23+
b = "abc"
24+
>b : Symbol(Derived.b, Decl(checkInheritedProperty.ts, 6, 14))
25+
}
26+
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
//// [tests/cases/compiler/checkInheritedProperty.ts] ////
2+
3+
=== checkInheritedProperty.ts ===
4+
class Base {
5+
>Base : Base
6+
> : ^^^^
7+
}
8+
9+
declare const BaseFactory: new() => Base & { c: string }
10+
>BaseFactory : new () => Base & { c: string; }
11+
> : ^^^^^^^^^^
12+
>c : string
13+
> : ^^^^^^
14+
15+
class Derived extends BaseFactory {
16+
>Derived : Derived
17+
> : ^^^^^^^
18+
>BaseFactory : Base & { c: string; }
19+
> : ^^^^^^^^^^^^ ^^^
20+
21+
a = this.b
22+
>a : string
23+
> : ^^^^^^
24+
>this.b : string
25+
> : ^^^^^^
26+
>this : this
27+
> : ^^^^
28+
>b : string
29+
> : ^^^^^^
30+
31+
b = "abc"
32+
>b : string
33+
> : ^^^^^^
34+
>"abc" : "abc"
35+
> : ^^^^^
36+
}
37+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
errorInUnnamedClassExpression.ts(5,14): error TS2715: Abstract property 'bar' in class 'Foo' cannot be accessed in the constructor.
2+
errorInUnnamedClassExpression.ts(7,5): error TS1253: Abstract properties can only appear within an abstract class.
3+
errorInUnnamedClassExpression.ts(7,14): error TS7008: Member 'bar' implicitly has an 'any' type.
4+
5+
6+
==== errorInUnnamedClassExpression.ts (3 errors) ====
7+
// https://github.com/microsoft/TypeScript/issues/62920
8+
9+
let Foo = class {
10+
constructor() {
11+
this.bar++;
12+
~~~
13+
!!! error TS2715: Abstract property 'bar' in class 'Foo' cannot be accessed in the constructor.
14+
}
15+
abstract bar;
16+
~~~~~~~~
17+
!!! error TS1253: Abstract properties can only appear within an abstract class.
18+
~~~
19+
!!! error TS7008: Member 'bar' implicitly has an 'any' type.
20+
};
21+
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
//// [tests/cases/compiler/errorInUnnamedClassExpression.ts] ////
2+
3+
=== errorInUnnamedClassExpression.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/62920
5+
6+
let Foo = class {
7+
>Foo : Symbol(Foo, Decl(errorInUnnamedClassExpression.ts, 2, 3))
8+
9+
constructor() {
10+
this.bar++;
11+
>this.bar : Symbol(Foo.bar, Decl(errorInUnnamedClassExpression.ts, 5, 5))
12+
>this : Symbol(Foo, Decl(errorInUnnamedClassExpression.ts, 2, 9))
13+
>bar : Symbol(Foo.bar, Decl(errorInUnnamedClassExpression.ts, 5, 5))
14+
}
15+
abstract bar;
16+
>bar : Symbol(Foo.bar, Decl(errorInUnnamedClassExpression.ts, 5, 5))
17+
18+
};
19+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//// [tests/cases/compiler/errorInUnnamedClassExpression.ts] ////
2+
3+
=== errorInUnnamedClassExpression.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/62920
5+
6+
let Foo = class {
7+
>Foo : typeof Foo
8+
> : ^^^^^^^^^^
9+
>class { constructor() { this.bar++; } abstract bar;} : typeof Foo
10+
> : ^^^^^^^^^^
11+
12+
constructor() {
13+
this.bar++;
14+
>this.bar++ : number
15+
> : ^^^^^^
16+
>this.bar : any
17+
> : ^^^
18+
>this : this
19+
> : ^^^^
20+
>bar : any
21+
> : ^^^
22+
}
23+
abstract bar;
24+
>bar : any
25+
> : ^^^
26+
27+
};
28+
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
noCrashOnMixin2.ts(11,33): error TS2370: A rest parameter must be of an array type.
2+
noCrashOnMixin2.ts(11,40): error TS1047: A rest parameter cannot be optional.
3+
noCrashOnMixin2.ts(14,12): error TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'.
4+
noCrashOnMixin2.ts(23,9): error TS2674: Constructor of class 'Abstract' is protected and only accessible within the class declaration.
5+
6+
7+
==== noCrashOnMixin2.ts (4 errors) ====
8+
// https://github.com/microsoft/TypeScript/issues/62921
9+
10+
class Abstract {
11+
protected constructor() {
12+
}
13+
}
14+
15+
class Concrete extends Abstract {
16+
}
17+
18+
type Constructor<T = {}> = new (...args?: any[]) => T;
19+
~~~~~~~~~~~~~~~
20+
!!! error TS2370: A rest parameter must be of an array type.
21+
~
22+
!!! error TS1047: A rest parameter cannot be optional.
23+
24+
function Mixin<TBase extends Constructor>(Base: TBase) {
25+
return class extends Base {
26+
~~~~~
27+
!!! error TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'.
28+
};
29+
}
30+
31+
class Empty {
32+
}
33+
34+
class CrashTrigger extends Mixin(Empty) {
35+
public trigger() {
36+
new Concrete();
37+
~~~~~~~~~~~~~~
38+
!!! error TS2674: Constructor of class 'Abstract' is protected and only accessible within the class declaration.
39+
}
40+
}
41+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
//// [tests/cases/compiler/noCrashOnMixin2.ts] ////
2+
3+
=== noCrashOnMixin2.ts ===
4+
// https://github.com/microsoft/TypeScript/issues/62921
5+
6+
class Abstract {
7+
>Abstract : Symbol(Abstract, Decl(noCrashOnMixin2.ts, 0, 0))
8+
9+
protected constructor() {
10+
}
11+
}
12+
13+
class Concrete extends Abstract {
14+
>Concrete : Symbol(Concrete, Decl(noCrashOnMixin2.ts, 5, 1))
15+
>Abstract : Symbol(Abstract, Decl(noCrashOnMixin2.ts, 0, 0))
16+
}
17+
18+
type Constructor<T = {}> = new (...args?: any[]) => T;
19+
>Constructor : Symbol(Constructor, Decl(noCrashOnMixin2.ts, 8, 1))
20+
>T : Symbol(T, Decl(noCrashOnMixin2.ts, 10, 17))
21+
>args : Symbol(args, Decl(noCrashOnMixin2.ts, 10, 32))
22+
>T : Symbol(T, Decl(noCrashOnMixin2.ts, 10, 17))
23+
24+
function Mixin<TBase extends Constructor>(Base: TBase) {
25+
>Mixin : Symbol(Mixin, Decl(noCrashOnMixin2.ts, 10, 54))
26+
>TBase : Symbol(TBase, Decl(noCrashOnMixin2.ts, 12, 15))
27+
>Constructor : Symbol(Constructor, Decl(noCrashOnMixin2.ts, 8, 1))
28+
>Base : Symbol(Base, Decl(noCrashOnMixin2.ts, 12, 42))
29+
>TBase : Symbol(TBase, Decl(noCrashOnMixin2.ts, 12, 15))
30+
31+
return class extends Base {
32+
>Base : Symbol(Base, Decl(noCrashOnMixin2.ts, 12, 42))
33+
34+
};
35+
}
36+
37+
class Empty {
38+
>Empty : Symbol(Empty, Decl(noCrashOnMixin2.ts, 15, 1))
39+
}
40+
41+
class CrashTrigger extends Mixin(Empty) {
42+
>CrashTrigger : Symbol(CrashTrigger, Decl(noCrashOnMixin2.ts, 18, 1))
43+
>Mixin : Symbol(Mixin, Decl(noCrashOnMixin2.ts, 10, 54))
44+
>Empty : Symbol(Empty, Decl(noCrashOnMixin2.ts, 15, 1))
45+
46+
public trigger() {
47+
>trigger : Symbol(CrashTrigger.trigger, Decl(noCrashOnMixin2.ts, 20, 41))
48+
49+
new Concrete();
50+
>Concrete : Symbol(Concrete, Decl(noCrashOnMixin2.ts, 5, 1))
51+
}
52+
}
53+

0 commit comments

Comments
 (0)