Fix get symbol at location to behave correctly for parameter assignments and jsx attributes#20706
Conversation
…nts and jsx attributes
cafb3c5 to
7405a9c
Compare
sandersn
left a comment
There was a problem hiding this comment.
Some minor questions left, although it turns out you either answered or fixed a lot of them.
| // 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.
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.
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.
| 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.
why can't these be shared any more? Are there order conflicts in the current, shared version?
There was a problem hiding this comment.
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.
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.
There's no noticeable difference in self-compilation (maybe slightly better? The difference is in the noise.).
| 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.
are these aliases meant to be public? I guess maybe they are required for export to services/
There was a problem hiding this comment.
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.
I don't care much either way, just checking.
|
|
||
| /** @type {string|undefined} */ | ||
| foo: undefined, | ||
| >foo : string | undefined |
There was a problem hiding this comment.
fix'd since this comment was first submitted
|
|
||
| for ({name: nameA } of robots) { | ||
| >{name: nameA } : { name: string; } | ||
| >name : Robot |
There was a problem hiding this comment.
this change is confusing. Either the baseline was wrong before or it's wrong now. I think it was wrong before.
| 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.
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.
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.
| 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.
:( 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.
Or just parent as TypeContainer.
| /** 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.
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).