Skip to content

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

Merged
3 commits merged into from
Aug 29, 2017

Conversation

ghost
Copy link

@ghost ghost commented Aug 18, 2017

Fixes #14822

@sandersn What's the proper way to get a superclass symbol from a class symbol?

@ghost ghost requested a review from sandersn August 18, 2017 21:21
if (isInPropertyInitializer(node) &&
!isBlockScopedNameDeclaredBeforeUse(valueDeclaration, right)
&& !isPropertyDeclaredInAncestorClass(prop)) {
error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, unescapeLeadingUnderscores(right.escapedText));
Copy link
Author

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"?

Copy link
Member

@sandersn sandersn left a 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.


// TODO: there must be a better way of doing this
function getSuperClass(classSymbol: Symbol): Symbol | undefined {
const classDecl = classSymbol.valueDeclaration;
Copy link
Member

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.

Copy link
Member

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.

Copy link
Member

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.

}

function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean {
// It's possible that "prop.valueDeclaration" is a local declaration, but the property was also declared in a superclass.
Copy link
Member

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

// 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);
Copy link
Member

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)

Copy link
Author

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.

Copy link
Member

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

@ghost
Copy link
Author

ghost commented Aug 29, 2017

@sandersn Any more comments?

*/
function isPropertyDeclaredInAncestorClass(prop: Symbol): boolean {
let classType = getTypeOfSymbol(prop.parent) as InterfaceType;
while (true) {
Copy link
Member

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.

@ghost ghost merged commit 7306b13 into master Aug 29, 2017
@ghost ghost deleted the useBeforeDeclaration_superClass branch August 29, 2017 16:18
@microsoft microsoft locked and limited conversation to collaborators Jun 14, 2018
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants