-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Fix get symbol at location to behave correctly for parameter assignments and jsx attributes #20706
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
Fix get symbol at location to behave correctly for parameter assignments and jsx attributes #20706
Conversation
…nts and jsx attributes
cafb3c5
to
7405a9c
Compare
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.
Some minor questions left, although it turns out you either answered or fixed a lot of them.
src/compiler/checker.ts
Outdated
@@ -4216,7 +4216,7 @@ namespace ts { | |||
|
|||
// Return the type of a binding element parent. We check SymbolLinks first to see if a type has been | |||
// assigned by contextual typing. | |||
function getTypeForBindingElementParent(node: VariableLikeDeclaration) { | |||
function getTypeForBindingElementParent(node: BindingElement["parent"]["parent"]) { |
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.
This is too cute + too obscure for me. Since it appears to be equivalent to VariableDeclaration | ParameterDeclaration | BindingElement
, why not use that or create an alias for it?
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 wanted to use BindingElement["parent"]["parent"]
so it stays in sync with changes to both binding elements' types and their parents' types - so an alias it is.
@@ -88,20 +88,48 @@ namespace ts { | |||
case SyntaxKind.SpreadAssignment: | |||
return visitNode(cbNode, (<SpreadAssignment>node).expression); | |||
case SyntaxKind.Parameter: | |||
return visitNodes(cbNode, cbNodes, node.decorators) || | |||
visitNodes(cbNode, cbNodes, node.modifiers) || | |||
visitNode(cbNode, (<ParameterDeclaration>node).dotDotDotToken) || |
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.
why can't these be shared any more? Are there order conflicts in the current, shared version?
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.
The union won't allow access to properties that don't exist on every node. Also, this is less polymorphic, so should have slightly better performance.
type?: TypeNode; | ||
initializer?: Expression; | ||
} | ||
export type VariableLikeDeclaration = |
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.
performance? I remember doing this (or similar) and found it added quite a bit of time to our build.
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.
There's no noticeable difference in self-compilation (maybe slightly better? The difference is in the noise.).
@@ -453,6 +453,9 @@ declare namespace ts { | |||
interface JSDocContainer { | |||
} | |||
type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | LabeledStatement | ExpressionStatement | VariableStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | EndOfFileToken; | |||
type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; |
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.
are these aliases meant to be public? I guess maybe they are required for export to services/
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 wanted to make them public (like HasJSDoc
), because knowing what nodes have a .type
or a .initializer
is a useful set of nodes, IMO. It can be internal, since I don't think any public functions use them?
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 don't care much either way, just checking.
@@ -10,12 +10,12 @@ const obj = { | |||
|
|||
/** @type {string|undefined} */ | |||
foo: undefined, | |||
>foo : string | 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.
this change seems incorrect
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.
fix'd since this comment was first submitted
@@ -103,7 +103,7 @@ let name: string, primary: string, secondary: string, skill: string; | |||
|
|||
for ({name: nameA } of robots) { | |||
>{name: nameA } : { name: string; } | |||
>name : Robot |
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.
this change is confusing. Either the baseline was wrong before or it's wrong now. I think it was wrong before.
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 was wrong before.
@@ -25,5 +25,5 @@ verify.referenceGroups(r2, [ | |||
]); | |||
verify.referenceGroups(r4, [ | |||
{ definition: "(property) I.property1: number", ranges: [r0, r1, r2, r3] }, | |||
{ definition: "(property) property1: I", ranges: [r4] } | |||
{ definition: "(property) property1: any", ranges: [r4] } |
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.
This is confusing. What is correct here? any
shouldn't be it, but I don't think I
is correct either.
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
was very wrong. any
is at least the type of p2
, which is bound to the same symbol as that property because the object literal at this location isn't being correctly interpreted as a binding pattern in all locations. This PR is like a partial fix for that (now the type isn't completely incorrect, at least), but the symbols still need to be bound up correctly. IMO, the root cause is object literal/binding pattern confusion causing us to not handle binding patterns correctly in all the places we need to. I'd like to do a more directed fix at making binding patterns actually appear in expression positions instead of object literals when they're actually binding patterns, and use that to fix this.
For now, this is much better, though.
src/compiler/utilities.ts
Outdated
@@ -784,7 +784,7 @@ namespace ts { | |||
case SyntaxKind.PropertySignature: | |||
case SyntaxKind.Parameter: | |||
case SyntaxKind.VariableDeclaration: | |||
return node === (<VariableLikeDeclaration>parent).type; | |||
return node === (parent as Node & { type: Node }).type; |
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.
:( parsing for humans (looks like (parent as Node) & { type: Node }
at first glance)
So wouldn't parent as HasType
work too? It would be easier to read.
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 just parent as TypeContainer
.
src/compiler/utilities.ts
Outdated
/** True if has type node attached to it. */ | ||
/* @internal */ | ||
export function hasType(node: Node): node is HasType { | ||
return !!(node as TypeContainer).type; |
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 drop TypeContainer and just use any
.
@sandersn Have I addressed all of your comments? |
Fixes #19041
The corrected type baselines have exposed another bug - note all the literal types in TSX files (opened #20705 to track it).