Skip to content

Commit 41c1a5b

Browse files
committed
Merge pull request #7945 from Microsoft/renameAndFindRef
Fixes rename for destructuring, named imports and default imports
2 parents 5b0b09c + c492fc6 commit 41c1a5b

27 files changed

+594
-92
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ rwc-report.html
2626
*.swp
2727
build.json
2828
*.actual
29+
tests/webTestServer.js
30+
tests/webTestServer.js.map
2931
tests/webhost/*.d.ts
3032
tests/webhost/webtsc.js
3133
tests/cases/**/*.js

src/compiler/checker.ts

Lines changed: 111 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ namespace ts {
8383
getShorthandAssignmentValueSymbol,
8484
getExportSpecifierLocalTargetSymbol,
8585
getTypeAtLocation: getTypeOfNode,
86+
getPropertySymbolOfDestructuringAssignment,
8687
typeToString,
8788
getSymbolDisplayBuilder,
8889
symbolToString,
@@ -11810,39 +11811,43 @@ namespace ts {
1181011811
function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
1181111812
const properties = node.properties;
1181211813
for (const p of properties) {
11813-
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
11814-
const name = <PropertyName>(<PropertyAssignment>p).name;
11815-
if (name.kind === SyntaxKind.ComputedPropertyName) {
11816-
checkComputedPropertyName(<ComputedPropertyName>name);
11817-
}
11818-
if (isComputedNonLiteralName(name)) {
11819-
continue;
11820-
}
11814+
checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, contextualMapper);
11815+
}
11816+
return sourceType;
11817+
}
1182111818

11822-
const text = getTextOfPropertyName(name);
11823-
const type = isTypeAny(sourceType)
11824-
? sourceType
11825-
: getTypeOfPropertyOfType(sourceType, text) ||
11826-
isNumericLiteralName(text) && getIndexTypeOfType(sourceType, IndexKind.Number) ||
11827-
getIndexTypeOfType(sourceType, IndexKind.String);
11828-
if (type) {
11829-
if (p.kind === SyntaxKind.ShorthandPropertyAssignment) {
11830-
checkDestructuringAssignment(<ShorthandPropertyAssignment>p, type);
11831-
}
11832-
else {
11833-
// non-shorthand property assignments should always have initializers
11834-
checkDestructuringAssignment((<PropertyAssignment>p).initializer, type);
11835-
}
11819+
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElement, contextualMapper?: TypeMapper) {
11820+
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
11821+
const name = <PropertyName>(<PropertyAssignment>property).name;
11822+
if (name.kind === SyntaxKind.ComputedPropertyName) {
11823+
checkComputedPropertyName(<ComputedPropertyName>name);
11824+
}
11825+
if (isComputedNonLiteralName(name)) {
11826+
return undefined;
11827+
}
11828+
11829+
const text = getTextOfPropertyName(name);
11830+
const type = isTypeAny(objectLiteralType)
11831+
? objectLiteralType
11832+
: getTypeOfPropertyOfType(objectLiteralType, text) ||
11833+
isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, IndexKind.Number) ||
11834+
getIndexTypeOfType(objectLiteralType, IndexKind.String);
11835+
if (type) {
11836+
if (property.kind === SyntaxKind.ShorthandPropertyAssignment) {
11837+
return checkDestructuringAssignment(<ShorthandPropertyAssignment>property, type);
1183611838
}
1183711839
else {
11838-
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(sourceType), declarationNameToString(name));
11840+
// non-shorthand property assignments should always have initializers
11841+
return checkDestructuringAssignment((<PropertyAssignment>property).initializer, type);
1183911842
}
1184011843
}
1184111844
else {
11842-
error(p, Diagnostics.Property_assignment_expected);
11845+
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
1184311846
}
1184411847
}
11845-
return sourceType;
11848+
else {
11849+
error(property, Diagnostics.Property_assignment_expected);
11850+
}
1184611851
}
1184711852

1184811853
function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
@@ -11852,44 +11857,51 @@ namespace ts {
1185211857
const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false) || unknownType;
1185311858
const elements = node.elements;
1185411859
for (let i = 0; i < elements.length; i++) {
11855-
const e = elements[i];
11856-
if (e.kind !== SyntaxKind.OmittedExpression) {
11857-
if (e.kind !== SyntaxKind.SpreadElementExpression) {
11858-
const propName = "" + i;
11859-
const type = isTypeAny(sourceType)
11860-
? sourceType
11861-
: isTupleLikeType(sourceType)
11862-
? getTypeOfPropertyOfType(sourceType, propName)
11863-
: elementType;
11864-
if (type) {
11865-
checkDestructuringAssignment(e, type, contextualMapper);
11860+
checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, contextualMapper);
11861+
}
11862+
return sourceType;
11863+
}
11864+
11865+
function checkArrayLiteralDestructuringElementAssignment(node: ArrayLiteralExpression, sourceType: Type,
11866+
elementIndex: number, elementType: Type, contextualMapper?: TypeMapper) {
11867+
const elements = node.elements;
11868+
const element = elements[elementIndex];
11869+
if (element.kind !== SyntaxKind.OmittedExpression) {
11870+
if (element.kind !== SyntaxKind.SpreadElementExpression) {
11871+
const propName = "" + elementIndex;
11872+
const type = isTypeAny(sourceType)
11873+
? sourceType
11874+
: isTupleLikeType(sourceType)
11875+
? getTypeOfPropertyOfType(sourceType, propName)
11876+
: elementType;
11877+
if (type) {
11878+
return checkDestructuringAssignment(element, type, contextualMapper);
11879+
}
11880+
else {
11881+
if (isTupleType(sourceType)) {
11882+
error(element, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), (<TupleType>sourceType).elementTypes.length, elements.length);
1186611883
}
1186711884
else {
11868-
if (isTupleType(sourceType)) {
11869-
error(e, Diagnostics.Tuple_type_0_with_length_1_cannot_be_assigned_to_tuple_with_length_2, typeToString(sourceType), (<TupleType>sourceType).elementTypes.length, elements.length);
11870-
}
11871-
else {
11872-
error(e, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
11873-
}
11885+
error(element, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
1187411886
}
1187511887
}
11888+
}
11889+
else {
11890+
if (elementIndex < elements.length - 1) {
11891+
error(element, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
11892+
}
1187611893
else {
11877-
if (i < elements.length - 1) {
11878-
error(e, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
11894+
const restExpression = (<SpreadElementExpression>element).expression;
11895+
if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
11896+
error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
1187911897
}
1188011898
else {
11881-
const restExpression = (<SpreadElementExpression>e).expression;
11882-
if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
11883-
error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
11884-
}
11885-
else {
11886-
checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
11887-
}
11899+
return checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
1188811900
}
1188911901
}
1189011902
}
1189111903
}
11892-
return sourceType;
11904+
return undefined;
1189311905
}
1189411906

1189511907
function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, contextualMapper?: TypeMapper): Type {
@@ -16562,6 +16574,53 @@ namespace ts {
1656216574
return unknownType;
1656316575
}
1656416576

16577+
// Gets the type of object literal or array literal of destructuring assignment.
16578+
// { a } from
16579+
// for ( { a } of elems) {
16580+
// }
16581+
// [ a ] from
16582+
// [a] = [ some array ...]
16583+
function getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr: Expression): Type {
16584+
Debug.assert(expr.kind === SyntaxKind.ObjectLiteralExpression || expr.kind === SyntaxKind.ArrayLiteralExpression);
16585+
// If this is from "for of"
16586+
// for ( { a } of elems) {
16587+
// }
16588+
if (expr.parent.kind === SyntaxKind.ForOfStatement) {
16589+
const iteratedType = checkRightHandSideOfForOf((<ForOfStatement>expr.parent).expression);
16590+
return checkDestructuringAssignment(expr, iteratedType || unknownType);
16591+
}
16592+
// If this is from "for" initializer
16593+
// for ({a } = elems[0];.....) { }
16594+
if (expr.parent.kind === SyntaxKind.BinaryExpression) {
16595+
const iteratedType = checkExpression((<BinaryExpression>expr.parent).right);
16596+
return checkDestructuringAssignment(expr, iteratedType || unknownType);
16597+
}
16598+
// If this is from nested object binding pattern
16599+
// for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) {
16600+
if (expr.parent.kind === SyntaxKind.PropertyAssignment) {
16601+
const typeOfParentObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>expr.parent.parent);
16602+
return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || unknownType, <ObjectLiteralElement>expr.parent);
16603+
}
16604+
// Array literal assignment - array destructuring pattern
16605+
Debug.assert(expr.parent.kind === SyntaxKind.ArrayLiteralExpression);
16606+
// [{ property1: p1, property2 }] = elems;
16607+
const typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>expr.parent);
16608+
const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false) || unknownType;
16609+
return checkArrayLiteralDestructuringElementAssignment(<ArrayLiteralExpression>expr.parent, typeOfArrayLiteral,
16610+
indexOf((<ArrayLiteralExpression>expr.parent).elements, expr), elementType || unknownType);
16611+
}
16612+
16613+
// Gets the property symbol corresponding to the property in destructuring assignment
16614+
// 'property1' from
16615+
// for ( { property1: a } of elems) {
16616+
// }
16617+
// 'property1' at location 'a' from:
16618+
// [a] = [ property1, property2 ]
16619+
function getPropertySymbolOfDestructuringAssignment(location: Identifier) {
16620+
// Get the type of the object or array literal and then look for property of given name in the type
16621+
const typeOfObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>location.parent.parent);
16622+
return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.text);
16623+
}
1656516624

1656616625
function getTypeOfExpression(expr: Expression): Type {
1656716626
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,6 +1741,7 @@ namespace ts {
17411741
getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[];
17421742
getShorthandAssignmentValueSymbol(location: Node): Symbol;
17431743
getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol;
1744+
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol;
17441745
getTypeAtLocation(node: Node): Type;
17451746
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
17461747
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;

0 commit comments

Comments
 (0)