Skip to content

Commit

Permalink
Merge pull request #7945 from Microsoft/renameAndFindRef
Browse files Browse the repository at this point in the history
Fixes rename for destructuring, named imports and default imports
  • Loading branch information
sheetalkamat committed Apr 13, 2016
2 parents 5b0b09c + c492fc6 commit 41c1a5b
Show file tree
Hide file tree
Showing 27 changed files with 594 additions and 92 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ rwc-report.html
*.swp
build.json
*.actual
tests/webTestServer.js
tests/webTestServer.js.map
tests/webhost/*.d.ts
tests/webhost/webtsc.js
tests/cases/**/*.js
Expand Down
163 changes: 111 additions & 52 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ namespace ts {
getShorthandAssignmentValueSymbol,
getExportSpecifierLocalTargetSymbol,
getTypeAtLocation: getTypeOfNode,
getPropertySymbolOfDestructuringAssignment,
typeToString,
getSymbolDisplayBuilder,
symbolToString,
Expand Down Expand Up @@ -11810,39 +11811,43 @@ namespace ts {
function checkObjectLiteralAssignment(node: ObjectLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
const properties = node.properties;
for (const p of properties) {
if (p.kind === SyntaxKind.PropertyAssignment || p.kind === SyntaxKind.ShorthandPropertyAssignment) {
const name = <PropertyName>(<PropertyAssignment>p).name;
if (name.kind === SyntaxKind.ComputedPropertyName) {
checkComputedPropertyName(<ComputedPropertyName>name);
}
if (isComputedNonLiteralName(name)) {
continue;
}
checkObjectLiteralDestructuringPropertyAssignment(sourceType, p, contextualMapper);
}
return sourceType;
}

const text = getTextOfPropertyName(name);
const type = isTypeAny(sourceType)
? sourceType
: getTypeOfPropertyOfType(sourceType, text) ||
isNumericLiteralName(text) && getIndexTypeOfType(sourceType, IndexKind.Number) ||
getIndexTypeOfType(sourceType, IndexKind.String);
if (type) {
if (p.kind === SyntaxKind.ShorthandPropertyAssignment) {
checkDestructuringAssignment(<ShorthandPropertyAssignment>p, type);
}
else {
// non-shorthand property assignments should always have initializers
checkDestructuringAssignment((<PropertyAssignment>p).initializer, type);
}
function checkObjectLiteralDestructuringPropertyAssignment(objectLiteralType: Type, property: ObjectLiteralElement, contextualMapper?: TypeMapper) {
if (property.kind === SyntaxKind.PropertyAssignment || property.kind === SyntaxKind.ShorthandPropertyAssignment) {
const name = <PropertyName>(<PropertyAssignment>property).name;
if (name.kind === SyntaxKind.ComputedPropertyName) {
checkComputedPropertyName(<ComputedPropertyName>name);
}
if (isComputedNonLiteralName(name)) {
return undefined;
}

const text = getTextOfPropertyName(name);
const type = isTypeAny(objectLiteralType)
? objectLiteralType
: getTypeOfPropertyOfType(objectLiteralType, text) ||
isNumericLiteralName(text) && getIndexTypeOfType(objectLiteralType, IndexKind.Number) ||
getIndexTypeOfType(objectLiteralType, IndexKind.String);
if (type) {
if (property.kind === SyntaxKind.ShorthandPropertyAssignment) {
return checkDestructuringAssignment(<ShorthandPropertyAssignment>property, type);
}
else {
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(sourceType), declarationNameToString(name));
// non-shorthand property assignments should always have initializers
return checkDestructuringAssignment((<PropertyAssignment>property).initializer, type);
}
}
else {
error(p, Diagnostics.Property_assignment_expected);
error(name, Diagnostics.Type_0_has_no_property_1_and_no_string_index_signature, typeToString(objectLiteralType), declarationNameToString(name));
}
}
return sourceType;
else {
error(property, Diagnostics.Property_assignment_expected);
}
}

function checkArrayLiteralAssignment(node: ArrayLiteralExpression, sourceType: Type, contextualMapper?: TypeMapper): Type {
Expand All @@ -11852,44 +11857,51 @@ namespace ts {
const elementType = checkIteratedTypeOrElementType(sourceType, node, /*allowStringInput*/ false) || unknownType;
const elements = node.elements;
for (let i = 0; i < elements.length; i++) {
const e = elements[i];
if (e.kind !== SyntaxKind.OmittedExpression) {
if (e.kind !== SyntaxKind.SpreadElementExpression) {
const propName = "" + i;
const type = isTypeAny(sourceType)
? sourceType
: isTupleLikeType(sourceType)
? getTypeOfPropertyOfType(sourceType, propName)
: elementType;
if (type) {
checkDestructuringAssignment(e, type, contextualMapper);
checkArrayLiteralDestructuringElementAssignment(node, sourceType, i, elementType, contextualMapper);
}
return sourceType;
}

function checkArrayLiteralDestructuringElementAssignment(node: ArrayLiteralExpression, sourceType: Type,
elementIndex: number, elementType: Type, contextualMapper?: TypeMapper) {
const elements = node.elements;
const element = elements[elementIndex];
if (element.kind !== SyntaxKind.OmittedExpression) {
if (element.kind !== SyntaxKind.SpreadElementExpression) {
const propName = "" + elementIndex;
const type = isTypeAny(sourceType)
? sourceType
: isTupleLikeType(sourceType)
? getTypeOfPropertyOfType(sourceType, propName)
: elementType;
if (type) {
return checkDestructuringAssignment(element, type, contextualMapper);
}
else {
if (isTupleType(sourceType)) {
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);
}
else {
if (isTupleType(sourceType)) {
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);
}
else {
error(e, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
}
error(element, Diagnostics.Type_0_has_no_property_1, typeToString(sourceType), propName);
}
}
}
else {
if (elementIndex < elements.length - 1) {
error(element, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
}
else {
if (i < elements.length - 1) {
error(e, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
const restExpression = (<SpreadElementExpression>element).expression;
if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
}
else {
const restExpression = (<SpreadElementExpression>e).expression;
if (restExpression.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>restExpression).operatorToken.kind === SyntaxKind.EqualsToken) {
error((<BinaryExpression>restExpression).operatorToken, Diagnostics.A_rest_element_cannot_have_an_initializer);
}
else {
checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
}
return checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
}
}
}
}
return sourceType;
return undefined;
}

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

// Gets the type of object literal or array literal of destructuring assignment.
// { a } from
// for ( { a } of elems) {
// }
// [ a ] from
// [a] = [ some array ...]
function getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(expr: Expression): Type {
Debug.assert(expr.kind === SyntaxKind.ObjectLiteralExpression || expr.kind === SyntaxKind.ArrayLiteralExpression);
// If this is from "for of"
// for ( { a } of elems) {
// }
if (expr.parent.kind === SyntaxKind.ForOfStatement) {
const iteratedType = checkRightHandSideOfForOf((<ForOfStatement>expr.parent).expression);
return checkDestructuringAssignment(expr, iteratedType || unknownType);
}
// If this is from "for" initializer
// for ({a } = elems[0];.....) { }
if (expr.parent.kind === SyntaxKind.BinaryExpression) {
const iteratedType = checkExpression((<BinaryExpression>expr.parent).right);
return checkDestructuringAssignment(expr, iteratedType || unknownType);
}
// If this is from nested object binding pattern
// for ({ skills: { primary, secondary } } = multiRobot, i = 0; i < 1; i++) {
if (expr.parent.kind === SyntaxKind.PropertyAssignment) {
const typeOfParentObjectLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>expr.parent.parent);
return checkObjectLiteralDestructuringPropertyAssignment(typeOfParentObjectLiteral || unknownType, <ObjectLiteralElement>expr.parent);
}
// Array literal assignment - array destructuring pattern
Debug.assert(expr.parent.kind === SyntaxKind.ArrayLiteralExpression);
// [{ property1: p1, property2 }] = elems;
const typeOfArrayLiteral = getTypeOfArrayLiteralOrObjectLiteralDestructuringAssignment(<Expression>expr.parent);
const elementType = checkIteratedTypeOrElementType(typeOfArrayLiteral || unknownType, expr.parent, /*allowStringInput*/ false) || unknownType;
return checkArrayLiteralDestructuringElementAssignment(<ArrayLiteralExpression>expr.parent, typeOfArrayLiteral,
indexOf((<ArrayLiteralExpression>expr.parent).elements, expr), elementType || unknownType);
}

// Gets the property symbol corresponding to the property in destructuring assignment
// 'property1' from
// for ( { property1: a } of elems) {
// }
// 'property1' at location 'a' from:
// [a] = [ property1, property2 ]
function getPropertySymbolOfDestructuringAssignment(location: Identifier) {
// 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);
}

function getTypeOfExpression(expr: Expression): Type {
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1741,6 +1741,7 @@ namespace ts {
getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: string): Symbol[];
getShorthandAssignmentValueSymbol(location: Node): Symbol;
getExportSpecifierLocalTargetSymbol(location: ExportSpecifier): Symbol;
getPropertySymbolOfDestructuringAssignment(location: Identifier): Symbol;
getTypeAtLocation(node: Node): Type;
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
Expand Down
Loading

0 comments on commit 41c1a5b

Please sign in to comment.