-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Get references and rename to include property in the search when short hand property assignment infers the property in the declaration #15850
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
Changes from all commits
89add94
94a2c48
31e07c3
f49ad71
7164675
f49d74a
395c9a9
57adfce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -121,7 +121,7 @@ namespace ts { | |
| return node ? getSymbolAtLocation(node) : undefined; | ||
| }, | ||
| getShorthandAssignmentValueSymbol: node => { | ||
| node = getParseTreeNode(node); | ||
| node = getParseTreeNode(node, isShorthandPropertyAssignment); | ||
| return node ? getShorthandAssignmentValueSymbol(node) : undefined; | ||
| }, | ||
| getExportSpecifierLocalTargetSymbol: node => { | ||
|
|
@@ -132,10 +132,6 @@ namespace ts { | |
| node = getParseTreeNode(node); | ||
| return node ? getTypeOfNode(node) : unknownType; | ||
| }, | ||
| getPropertySymbolOfDestructuringAssignment: location => { | ||
| location = getParseTreeNode(location, isIdentifier); | ||
| return location ? getPropertySymbolOfDestructuringAssignment(location) : undefined; | ||
| }, | ||
| signatureToString: (signature, enclosingDeclaration?, flags?, kind?) => { | ||
| return signatureToString(signature, getParseTreeNode(enclosingDeclaration), flags, kind); | ||
| }, | ||
|
|
@@ -10733,11 +10729,6 @@ namespace ts { | |
| getTypeOfExpression(node.right); | ||
| } | ||
|
|
||
| function isDestructuringAssignmentTarget(parent: Node) { | ||
| return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent || | ||
| parent.parent.kind === SyntaxKind.ForOfStatement && (parent.parent as ForOfStatement).initializer === parent; | ||
| } | ||
|
|
||
| function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type { | ||
| return getTypeOfDestructuredArrayElement(getAssignedType(node), indexOf(node.elements, element)); | ||
| } | ||
|
|
@@ -16824,12 +16815,7 @@ namespace ts { | |
| if (exprOrAssignment.kind === SyntaxKind.ShorthandPropertyAssignment) { | ||
| const prop = <ShorthandPropertyAssignment>exprOrAssignment; | ||
| if (prop.objectAssignmentInitializer) { | ||
| // In strict null checking mode, if a default value of a non-undefined type is specified, remove | ||
| // undefined from the final type. | ||
| if (strictNullChecks && | ||
| !(getFalsyFlags(checkExpression(prop.objectAssignmentInitializer)) & TypeFlags.Undefined)) { | ||
| sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); | ||
| } | ||
| sourceType = updateTypeFromShorthandAssignmentInitializer(prop.objectAssignmentInitializer, sourceType); | ||
| checkBinaryLikeExpression(prop.name, prop.equalsToken, prop.objectAssignmentInitializer, checkMode); | ||
| } | ||
| target = (<ShorthandPropertyAssignment>exprOrAssignment).name; | ||
|
|
@@ -16851,6 +16837,16 @@ namespace ts { | |
| return checkReferenceAssignment(target, sourceType, checkMode); | ||
| } | ||
|
|
||
| function updateTypeFromShorthandAssignmentInitializer(objectAssignmentInitializer: Expression, sourceType: Type) { | ||
| // In strict null checking mode, if a default value of a non-undefined type is specified, remove | ||
| // undefined from the final type. | ||
| if (strictNullChecks && | ||
| !(getFalsyFlags(checkExpression(objectAssignmentInitializer)) & TypeFlags.Undefined)) { | ||
| sourceType = getTypeWithFacts(sourceType, TypeFacts.NEUndefined); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just |
||
| } | ||
| return sourceType; | ||
| } | ||
|
|
||
| function checkReferenceAssignment(target: Expression, sourceType: Type, checkMode?: CheckMode): Type { | ||
| const targetType = checkExpression(target, checkMode); | ||
| const error = target.parent.kind === SyntaxKind.SpreadAssignment ? | ||
|
|
@@ -22267,6 +22263,25 @@ namespace ts { | |
| return undefined; | ||
| } | ||
|
|
||
| function isDeclarationNameOfPropertyFromDestructuringAssignmentTarget(node: Node): node is PropertyName { | ||
| return (isShorthandPropertyAssignment(node.parent) || isPropertyAssignment(node.parent)) && | ||
| isObjectLiteralExpression(node.parent.parent) && | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this check necessary? Maybe we should add |
||
| isFromDestructuringAssignmentPatternTarget(node.parent.parent); | ||
| } | ||
|
|
||
| function getSymbolOfNodeFromDeclarationName(node: Node) { | ||
| // If the location is name of property from object literal destructuring pattern | ||
| // Get the property symbol from the object literal's type | ||
| // In below eg. get 'property' from type of elems iterating type | ||
| // for ({ property: p2 } of elems) { } | ||
| if (isDeclarationNameOfPropertyFromDestructuringAssignmentTarget(node)) { | ||
| return getPropertySymbolOfDestructuringAssignment(node); | ||
| } | ||
|
|
||
| // This is a declaration, call getSymbolOfNode | ||
| return getSymbolOfNode(node.parent); | ||
| } | ||
|
|
||
| function getSymbolAtLocation(node: Node) { | ||
| if (node.kind === SyntaxKind.SourceFile) { | ||
| return isExternalModule(<SourceFile>node) ? getMergedSymbol(node.symbol) : undefined; | ||
|
|
@@ -22279,10 +22294,10 @@ namespace ts { | |
|
|
||
| if (isDeclarationNameOrImportPropertyName(node)) { | ||
| // This is a declaration, call getSymbolOfNode | ||
| return getSymbolOfNode(node.parent); | ||
| return getSymbolOfNodeFromDeclarationName(node); | ||
| } | ||
| else if (isLiteralComputedPropertyDeclarationName(node)) { | ||
| return getSymbolOfNode(node.parent.parent); | ||
| return getSymbolOfNodeFromDeclarationName(node.parent); | ||
| } | ||
|
|
||
| if (node.kind === SyntaxKind.Identifier) { | ||
|
|
@@ -22359,14 +22374,11 @@ namespace ts { | |
| return undefined; | ||
| } | ||
|
|
||
| function getShorthandAssignmentValueSymbol(location: Node): Symbol { | ||
| function getShorthandAssignmentValueSymbol(location: ShorthandPropertyAssignment): Symbol { | ||
| // The function returns a value symbol of an identifier in the short-hand property assignment. | ||
| // This is necessary as an identifier in short-hand property assignment can contains two meaning: | ||
| // property name and property value. | ||
| if (location && location.kind === SyntaxKind.ShorthandPropertyAssignment) { | ||
| return resolveEntityName((<ShorthandPropertyAssignment>location).name, SymbolFlags.Value | SymbolFlags.Alias); | ||
| } | ||
| return undefined; | ||
| return resolveEntityName(location.name, SymbolFlags.Value | SymbolFlags.Alias); | ||
| } | ||
|
|
||
| /** Returns the target of an export specifier without following aliases */ | ||
|
|
@@ -22395,6 +22407,9 @@ namespace ts { | |
| } | ||
|
|
||
| if (isPartOfExpression(node)) { | ||
| if (isFromDestructuringAssignmentPatternTarget(node)) { | ||
| return getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(node); | ||
| } | ||
| return getRegularTypeOfExpression(<Expression>node); | ||
| } | ||
|
|
||
|
|
@@ -22424,7 +22439,27 @@ namespace ts { | |
| return getTypeOfSymbol(symbol); | ||
| } | ||
|
|
||
| if (isDeclarationNameOrImportPropertyName(node)) { | ||
| if (isDeclarationNameOrImportPropertyName(node) || isLiteralComputedPropertyDeclarationName(node)) { | ||
| const propertyName = isDeclarationName(node) ? node : node.parent; | ||
| // If the location is name of property from object literal destructuring pattern | ||
| // Get the property symbol from the object literal's type and get the type from there | ||
| // In below eg. get type of 'property' from type of elems iterating type | ||
| // for ({ property: p2 } of elems) { } | ||
| if (isDeclarationNameOfPropertyFromDestructuringAssignmentTarget(propertyName)) { | ||
| // Get the type of the object or array literal and then look for property of given name in the type | ||
| const objectLiteralType = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>propertyName.parent.parent); | ||
| const text = getTextOfPropertyName(propertyName); | ||
| let type = isTypeAny(objectLiteralType) | ||
| ? objectLiteralType | ||
| : getTypeOfPropertyOfType(objectLiteralType, text) || | ||
| isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, IndexKind.Number) || | ||
| getIndexTypeOfType(objectLiteralType, IndexKind.String); | ||
| if (type && isShorthandPropertyAssignment(propertyName.parent) && propertyName.parent.objectAssignmentInitializer) { | ||
| // Update the type with strict null check flags | ||
| type = updateTypeFromShorthandAssignmentInitializer(propertyName.parent.objectAssignmentInitializer, type); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: Just return early. |
||
| } | ||
| return type; | ||
| } | ||
| const symbol = getSymbolAtLocation(node); | ||
| return symbol && getTypeOfSymbol(symbol); | ||
| } | ||
|
|
@@ -22484,10 +22519,10 @@ namespace ts { | |
| // } | ||
| // 'property1' at location 'a' from: | ||
| // [a] = [ property1, property2 ] | ||
| function getPropertySymbolOfDestructuringAssignment(location: Identifier) { | ||
| function getPropertySymbolOfDestructuringAssignment(location: PropertyName) { | ||
| // Get the type of the object or array literal and then look for property of given name in the type | ||
| const typeOfObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>location.parent.parent); | ||
| return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.text); | ||
| return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, getTextOfPropertyName(location)); | ||
| } | ||
|
|
||
| function getRegularTypeOfExpression(expr: Expression): Type { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2529,9 +2529,8 @@ namespace ts { | |
| getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[]; | ||
| getSymbolAtLocation(node: Node): Symbol; | ||
| getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[]; | ||
| getShorthandAssignmentValueSymbol(location: Node): Symbol; | ||
| getShorthandAssignmentValueSymbol(location: ShorthandPropertyAssignment): Symbol; | ||
| getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol; | ||
| getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a breaking change, can you document why it's removed and what people should do instead? |
||
| getTypeAtLocation(node: Node): Type; | ||
| getTypeFromTypeNode(node: TypeNode): Type; | ||
| signatureToString(signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): string; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3754,6 +3754,38 @@ namespace ts { | |
| || kind === SyntaxKind.ObjectLiteralExpression; | ||
| } | ||
|
|
||
| export function isDestructuringAssignmentTarget(node: Node) { | ||
| // [a,b,c] from: | ||
| // [a, b, c] = someExpression; | ||
| return isAssignmentExpression(node.parent, /*excludeCompoundAssignment*/ true) && node.parent.left === node || | ||
| // [a, b, c] from: | ||
| // for([a, b, c] of expression) | ||
| node.parent.kind === SyntaxKind.ForOfStatement && (node.parent as ForOfStatement).initializer === node; | ||
| } | ||
|
|
||
| export function isFromDestructuringAssignmentPatternTarget(node: Node): node is AssignmentPattern { | ||
| if (isAssignmentPattern(node)) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: I would use an early return here. |
||
| // [a,b,c] from: | ||
| // [a, b, c] = someExpression; | ||
| // or | ||
| // [a, b, c] from: | ||
| // for([a, b, c] of expression) | ||
| if (isDestructuringAssignmentTarget(node)) { | ||
| return true; | ||
| } | ||
|
|
||
| // [a, b, c] of | ||
| // [x, [a, b, c] ] = someExpression | ||
| // or | ||
| // {x, a: {a, b, c} } = someExpression | ||
| if (isFromDestructuringAssignmentPatternTarget(node.parent.kind === SyntaxKind.PropertyAssignment ? node.parent.parent : node.parent)) { | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| return false; | ||
| } | ||
|
|
||
| export function isBindingElement(node: Node): node is BindingElement { | ||
| return node.kind === SyntaxKind.BindingElement; | ||
| } | ||
|
|
||
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 safe if
checkExpressionis called from insidegetTypeOfNode? Could that cause duplicate diagnostics?