-
Notifications
You must be signed in to change notification settings - Fork 13k
Don't issue a use-before-declared error for a property that exists in a superclass #17910
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
Conversation
src/compiler/checker.ts
Outdated
if (isInPropertyInitializer(node) && | ||
!isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right) | ||
&& !isPropertyDeclaredInAncestorClass(prop)) { | ||
error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, unescapeLeadingUnderscores(right.escapedText)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we change this to say "property" instead of "block-scoped variable"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good, although I want to see what it looks like after changing to use getBaseTypes.
src/compiler/checker.ts
Outdated
|
||
// TODO: there must be a better way of doing this | ||
function getSuperClass(classSymbol: Symbol): Symbol | undefined { | ||
const classDecl = classSymbol.valueDeclaration; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return getBaseTypes(getTypeOfSymbol(classSymbol)).map(t => t.symbol);
but this makes the return type Symbol[]
not Symbol | undefined
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, maybe this only applies to base types that are classes, in which case you can filter for that and assert that there's only one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe assume that there's only one; I believe that the code for getBaseTypes
is pretty clear that there's only one.
src/compiler/checker.ts
Outdated
} | ||
|
||
function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean { | ||
// It's possible that "prop.valueDeclaration" is a local declaration, but the property was also declared in a superclass. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use jsdoc syntax for this comment
src/compiler/checker.ts
Outdated
// In that case we won't consider it used before its declaration, because it gets its value from the superclass' declaration. | ||
let classSymbol = prop.parent; | ||
while (true) { | ||
classSymbol = getSuperClass(classSymbol); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would change getSuperClass
to return Type
, rename classSymbol
to classType
, and then change to const superProperty = getPropertyOfType(classType)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it not safe to access members
directly? We should document that if so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the main point is to switch to retrieving the super Type
instead of the Symbol
. After that, the correct/easiest way to retrieve the property symbol is getPropertyOfType
not type.symbol.members.get
@sandersn Any more comments? |
*/ | ||
function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean { | ||
let classType = getTypeOfSymbol(prop.parent) as InterfaceType; | ||
while (true) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It sure would be convenient to say while (classType = getSuperClass(classType))
here, but we only use this idiom one other place in checker, so perhaps not good to start now.
Fixes #14822
@sandersn What's the proper way to get a superclass symbol from a class symbol?