mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-11 02:15:10 -05:00
Added error for class properties used within their own declaration
Fixes #5987. Usages of a class property in a preceding property already gave an error, but the following doesn't yet: ```ts class Test { x: number = this.x; } ``` As with other use-before-declare checking, IIFEs are not treated as invalid uses.
This commit is contained in:
@@ -1118,6 +1118,9 @@ namespace ts {
|
||||
// still might be illegal if the usage is within a computed property name in the class (eg class A { static p = "a"; [A.p]() {} })
|
||||
return !findAncestor(usage, n => isComputedPropertyName(n) && n.parent.parent === declaration);
|
||||
}
|
||||
else if (isPropertyDeclaration(declaration)) {
|
||||
return isPropertyImmediatelyReferencedWithinDeclaration(declaration, usage);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1192,6 +1195,40 @@ namespace ts {
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function isPropertyImmediatelyReferencedWithinDeclaration(declaration: PropertyDeclaration, usage: Node) {
|
||||
// always legal if usage is after declaration
|
||||
if (usage.end > declaration.end) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// still might be legal if usage is deferred (e.g. x: any = () => this.x)
|
||||
// otherwise illegal if immediately referenced within the declaration (e.g. x: any = this.x)
|
||||
const ancestorChangingReferenceScope = findAncestor(usage, (node: Node) => {
|
||||
if (node === declaration) {
|
||||
return "quit";
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ArrowFunction:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return true;
|
||||
case SyntaxKind.Block:
|
||||
switch (node.parent.kind) {
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return ancestorChangingReferenceScope !== undefined && ancestorChangingReferenceScope !== declaration;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -19140,6 +19177,12 @@ namespace ts {
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
// We might be in `a = { b: this.b }`, so keep looking. See `tests/cases/compiler/useBeforeDeclaration_propertyAssignment.ts`.
|
||||
return false;
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
case SyntaxKind.HeritageClause:
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return false;
|
||||
default:
|
||||
return isExpressionNode(node) ? false : "quit";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user