Merge pull request #7945 from Microsoft/renameAndFindRef

Fixes rename for destructuring, named imports and default imports
This commit is contained in:
Sheetal Nandi 2016-04-13 15:46:43 -07:00
commit 41c1a5b497
27 changed files with 597 additions and 95 deletions

2
.gitignore vendored
View File

@ -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

View File

@ -83,6 +83,7 @@ namespace ts {
getShorthandAssignmentValueSymbol,
getExportSpecifierLocalTargetSymbol,
getTypeAtLocation: getTypeOfNode,
getPropertySymbolOfDestructuringAssignment,
typeToString,
getSymbolDisplayBuilder,
symbolToString,
@ -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 {
@ -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);
}
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);
}
}
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 (i < elements.length - 1) {
error(e, Diagnostics.A_rest_element_must_be_last_in_an_array_destructuring_pattern);
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 {
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);
}
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 {
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 {
return checkDestructuringAssignment(restExpression, createArrayType(elementType), contextualMapper);
}
}
}
}
return sourceType;
return undefined;
}
function checkDestructuringAssignment(exprOrAssignment: Expression | ShorthandPropertyAssignment, sourceType: Type, contextualMapper?: TypeMapper): Type {
@ -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)) {

View File

@ -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;

View File

@ -5660,8 +5660,51 @@ namespace ts {
};
}
function isImportSpecifierSymbol(symbol: Symbol) {
return (symbol.flags & SymbolFlags.Alias) && !!getDeclarationOfKind(symbol, SyntaxKind.ImportSpecifier);
function getAliasSymbolForPropertyNameSymbol(symbol: Symbol, location: Node): Symbol {
if (symbol.flags & SymbolFlags.Alias) {
// Default import get alias
const defaultImport = getDeclarationOfKind(symbol, SyntaxKind.ImportClause);
if (defaultImport) {
return typeChecker.getAliasedSymbol(symbol);
}
const importOrExportSpecifier = <ImportOrExportSpecifier>forEach(symbol.declarations,
declaration => (declaration.kind === SyntaxKind.ImportSpecifier ||
declaration.kind === SyntaxKind.ExportSpecifier) ? declaration : undefined);
if (importOrExportSpecifier &&
// export { a }
(!importOrExportSpecifier.propertyName ||
// export {a as class } where a is location
importOrExportSpecifier.propertyName === location)) {
// If Import specifier -> get alias
// else Export specifier -> get local target
return importOrExportSpecifier.kind === SyntaxKind.ImportSpecifier ?
typeChecker.getAliasedSymbol(symbol) :
typeChecker.getExportSpecifierLocalTargetSymbol(importOrExportSpecifier);
}
}
return undefined;
}
function getPropertySymbolOfDestructuringAssignment(location: Node) {
return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent) &&
typeChecker.getPropertySymbolOfDestructuringAssignment(<Identifier>location);
}
function isObjectBindingPatternElementWithoutPropertyName(symbol: Symbol) {
const bindingElement = <BindingElement>getDeclarationOfKind(symbol, SyntaxKind.BindingElement);
return bindingElement &&
bindingElement.parent.kind === SyntaxKind.ObjectBindingPattern &&
!bindingElement.propertyName;
}
function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol) {
if (isObjectBindingPatternElementWithoutPropertyName(symbol)) {
const bindingElement = <BindingElement>getDeclarationOfKind(symbol, SyntaxKind.BindingElement);
const typeOfPattern = typeChecker.getTypeAtLocation(bindingElement.parent);
return typeOfPattern && typeChecker.getPropertyOfType(typeOfPattern, (<Identifier>bindingElement.name).text);
}
return undefined;
}
function getInternedName(symbol: Symbol, location: Node, declarations: Declaration[]): string {
@ -5709,6 +5752,12 @@ namespace ts {
return undefined;
}
// If symbol is of object binding pattern element without property name we would want to
// look for property too and that could be anywhere
if (isObjectBindingPatternElementWithoutPropertyName(symbol)) {
return undefined;
}
// if this symbol is visible from its parent container, e.g. exported, then bail out
// if symbol correspond to the union property - bail out
if (symbol.parent || (symbol.flags & SymbolFlags.SyntheticProperty)) {
@ -6104,18 +6153,30 @@ namespace ts {
// The search set contains at least the current symbol
let result = [symbol];
// If the symbol is an alias, add what it aliases to the list
if (isImportSpecifierSymbol(symbol)) {
result.push(typeChecker.getAliasedSymbol(symbol));
// If the location is name of property symbol from object literal destructuring pattern
// Search the property symbol
// for ( { property: p2 } of elems) { }
if (isNameOfPropertyAssignment(location) && location.parent.kind !== SyntaxKind.ShorthandPropertyAssignment) {
const propertySymbol = getPropertySymbolOfDestructuringAssignment(location);
if (propertySymbol) {
result.push(propertySymbol);
}
}
// For export specifiers, the exported name can be referring to a local symbol, e.g.:
// If the symbol is an alias, add what it aliases to the list
// import {a} from "mod";
// export {a as somethingElse}
// We want the *local* declaration of 'a' as declared in the import,
// *not* as declared within "mod" (or farther)
if (location.parent.kind === SyntaxKind.ExportSpecifier) {
result.push(typeChecker.getExportSpecifierLocalTargetSymbol(<ExportSpecifier>location.parent));
// export {a}
// If the symbol is an alias to default declaration, add what it aliases to the list
// declare "mod" { export default class B { } }
// import B from "mod";
//// For export specifiers, the exported name can be referring to a local symbol, e.g.:
//// import {a} from "mod";
//// export {a as somethingElse}
//// We want the *local* declaration of 'a' as declared in the import,
//// *not* as declared within "mod" (or farther)
const aliasSymbol = getAliasSymbolForPropertyNameSymbol(symbol, location);
if (aliasSymbol) {
result = result.concat(populateSearchSymbolSet(aliasSymbol, location));
}
// If the location is in a context sensitive location (i.e. in an object literal) try
@ -6152,6 +6213,13 @@ namespace ts {
result = result.concat(typeChecker.getSymbolsOfParameterPropertyDeclaration(<ParameterDeclaration>symbol.valueDeclaration, symbol.name));
}
// If this is symbol of binding element without propertyName declaration in Object binding pattern
// Include the property in the search
const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol);
if (bindingElementPropertySymbol) {
result.push(bindingElementPropertySymbol);
}
// If this is a union property, add all the symbols from all its source symbols in all unioned types.
// If the symbol is an instantiation from a another symbol (e.g. widened symbol) , add the root the list
forEach(typeChecker.getRootSymbols(symbol), rootSymbol => {
@ -6233,32 +6301,40 @@ namespace ts {
}
// If the reference symbol is an alias, check if what it is aliasing is one of the search
// symbols.
if (isImportSpecifierSymbol(referenceSymbol)) {
const aliasedSymbol = typeChecker.getAliasedSymbol(referenceSymbol);
if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
return aliasedSymbol;
}
}
// For export specifiers, it can be a local symbol, e.g.
// import {a} from "mod";
// export {a as somethingElse}
// We want the local target of the export (i.e. the import symbol) and not the final target (i.e. "mod".a)
if (referenceLocation.parent.kind === SyntaxKind.ExportSpecifier) {
const aliasedSymbol = typeChecker.getExportSpecifierLocalTargetSymbol(<ExportSpecifier>referenceLocation.parent);
if (searchSymbols.indexOf(aliasedSymbol) >= 0) {
return aliasedSymbol;
}
// symbols but by looking up for related symbol of this alias so it can handle multiple level of indirectness.
const aliasSymbol = getAliasSymbolForPropertyNameSymbol(referenceSymbol, referenceLocation);
if (aliasSymbol) {
return getRelatedSymbol(searchSymbols, aliasSymbol, referenceLocation);
}
// If the reference location is in an object literal, try to get the contextual type for the
// object literal, lookup the property symbol in the contextual type, and use this symbol to
// compare to our searchSymbol
if (isNameOfPropertyAssignment(referenceLocation)) {
return forEach(getPropertySymbolsFromContextualType(referenceLocation), contextualSymbol => {
const contextualSymbol = forEach(getPropertySymbolsFromContextualType(referenceLocation), contextualSymbol => {
return forEach(typeChecker.getRootSymbols(contextualSymbol), s => searchSymbols.indexOf(s) >= 0 ? s : undefined);
});
if (contextualSymbol) {
return contextualSymbol;
}
// If the reference location is the name of property from object literal destructuring pattern
// Get the property symbol from the object literal's type and look if thats the search symbol
// In below eg. get 'property' from type of elems iterating type
// for ( { property: p2 } of elems) { }
const propertySymbol = getPropertySymbolOfDestructuringAssignment(referenceLocation);
if (propertySymbol && searchSymbols.indexOf(propertySymbol) >= 0) {
return propertySymbol;
}
}
// If the reference location is the binding element and doesn't have property name
// then include the binding element in the related symbols
// let { a } : { a };
const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(referenceSymbol);
if (bindingElementPropertySymbol && searchSymbols.indexOf(bindingElementPropertySymbol) >= 0) {
return bindingElementPropertySymbol;
}
// Unwrap symbols to get to the root (e.g. transient symbols as a result of widening)

View File

@ -6,7 +6,7 @@
////}
////
////var foo: I;
////var [{ [|property1|]: prop1 }, { property1, property2 } ] = [foo, foo];
////var [{ [|property1|]: prop1 }, { [|property1|], property2 } ] = [foo, foo];
let ranges = test.ranges();
for (let range of ranges) {

View File

@ -6,14 +6,12 @@
////}
////
////function f({ /**/[|property1|]: p1 }: I,
//// { /*SHOULD_BE_A_REFERENCE*/property1 }: I,
//// { [|property1|] }: I,
//// { property1: p2 }) {
////
//// return property1 + 1;
//// return [|property1|] + 1;
////}
// NOTE: In the future, the identifier at
// SHOULD_BE_A_REFERENCE should be in the set of ranges.
goTo.marker();
let ranges = test.ranges();

View File

@ -8,12 +8,12 @@
////var elems: I[];
////for (let { [|property1|]: p } of elems) {
////}
////for (let { property1 } of elems) {
////for (let { [|property1|] } of elems) {
////}
////for (var { [|property1|]: p1 } of elems) {
////}
////var p2;
////for ({ property1 : p2 } of elems) {
////for ({ [|property1|] : p2 } of elems) {
////}
// Note: if this test ever changes, consider updating

View File

@ -1,19 +1,17 @@
/// <reference path='fourslash.ts'/>
////interface I {
//// /*SHOULD_BE_A_REFERENCE1*/property1: number;
//// [|property1|]: number;
//// property2: string;
////}
////
////function f({ /*SHOULD_BE_A_REFERENCE2*/property1: p1 }: I,
////function f({ [|property1|]: p1 }: I,
//// { /**/[|property1|] }: I,
//// { property1: p2 }) {
////
//// return [|property1|] + 1;
////}
// NOTE: In the future, the identifiers at
// SHOULD_BE_A_REFERENCE[1/2] should be in the set of ranges.
goTo.marker();
let ranges = test.ranges();

View File

@ -0,0 +1,19 @@
/// <reference path='fourslash.ts' />
// @Filename: B.ts
////export default class [|B|] {
//// test() {
//// }
////}
// @Filename: A.ts
////import [|B|] from "./B";
////let b = new [|B|]();
////b.test();
let ranges = test.ranges()
for (let range of ranges) {
goTo.file(range.fileName);
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
// @Filename: B.ts
////export default class /*1*/C {
//// test() {
//// }
////}
// @Filename: A.ts
////import [|B|] from "./B";
////let b = new [|B|]();
////b.test();
goTo.file("B.ts");
goTo.marker("1");
verify.occurrencesAtPositionCount(1);
goTo.file("A.ts");
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,14 @@
/// <reference path='fourslash.ts' />
////interface I {
//// [|x|]: number;
////}
////var a: I;
////var x;
////({ [|x|]: x } = a);
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
////interface I {
//// /*1*/[|property1|]: number;
//// property2: string;
////}
////var elems: I[];
////
////var p2: number, property1: number;
////for ({ [|property1|] } = elems[0]; p2 < 100; p2++) {
//// p2 = property1++;
////}
////for ({ /*2*/[|property1|]: p2 } = elems[0]; p2 < 100; p2++) {
////}
goTo.marker("1");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
goTo.marker("2");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);

View File

@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
////interface I {
//// property1: number;
//// property2: string;
////}
////var elems: I[];
////
////var p2: number, [|property1|]: number;
////for ({ [|property1|] } = elems[0]; p2 < 100; p2++) {
//// p2 = [|property1|]++;
////}
////for ({ property1: p2 } = elems[0]; p2 < 100; p2++) {
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
////interface I {
//// /*1*/[|property1|]: number;
//// property2: string;
////}
////var elems: I[];
////
////var property1: number, p2: number;
////for ({ [|property1|] } of elems) {
//// property1++;
////}
////for ({ /*2*/[|property1|]: p2 } of elems) {
////}
goTo.marker("1");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
goTo.marker("2");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);

View File

@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
////interface I {
//// property1: number;
//// property2: string;
////}
////var elems: I[];
////
////var [|property1|]: number, p2: number;
////for ({ [|property1|] } of elems) {
//// [|property1|]++;
////}
////for ({ property1: p2 } of elems) {
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,15 @@
/// <reference path='fourslash.ts' />
////interface I {
//// /*1*/[|property1|]: number;
//// property2: string;
////}
////var elems: I[], p1: number, property1: number;
////[{ /*2*/[|property1|]: p1 }] = elems;
////[{ [|property1|] }] = elems;
goTo.marker("1");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
goTo.marker("2");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);

View File

@ -0,0 +1,15 @@
/// <reference path='fourslash.ts' />
////interface I {
//// property1: number;
//// property2: string;
////}
////var elems: I[], p1: number, [|property1|]: number;
////[{ property1: p1 }] = elems;
////[{ [|property1|] }] = elems;
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,22 @@
/// <reference path='fourslash.ts' />
////interface MultiRobot {
//// name: string;
//// skills: {
//// /*1*/[|primary|]: string;
//// secondary: string;
//// };
////}
////let multiRobot: MultiRobot;
////for ({ skills: { /*2*/[|primary|]: primaryA, secondary: secondaryA } } = multiRobot, i = 0; i < 1; i++) {
//// console.log(primaryA);
////}
////for ({ skills: { [|primary|], secondary } } = multiRobot, i = 0; i < 1; i++) {
//// console.log(primary);
////}
goTo.marker("1");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
goTo.marker("2");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);

View File

@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
////interface MultiRobot {
//// name: string;
//// skills: {
//// primary: string;
//// secondary: string;
//// };
////}
////let multiRobot: MultiRobot, [|primary|]: string;
////for ({ skills: { primary: primaryA, secondary: secondaryA } } = multiRobot, i = 0; i < 1; i++) {
//// console.log(primaryA);
////}
////for ({ skills: { [|primary|], secondary } } = multiRobot, i = 0; i < 1; i++) {
//// console.log([|primary|]);
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,22 @@
/// <reference path='fourslash.ts' />
////interface MultiRobot {
//// name: string;
//// skills: {
//// /*1*/[|primary|]: string;
//// secondary: string;
//// };
////}
////let multiRobots: MultiRobot[];
////for ({ skills: { /*2*/[|primary|]: primaryA, secondary: secondaryA } } of multiRobots) {
//// console.log(primaryA);
////}
////for ({ skills: { [|primary|], secondary } } of multiRobots) {
//// console.log(primary);
////}
goTo.marker("1");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
goTo.marker("2");
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);

View File

@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
////interface MultiRobot {
//// name: string;
//// skills: {
//// primary: string;
//// secondary: string;
//// };
////}
////let multiRobots: MultiRobot[], [|primary|]: string;
////for ({ skills: { primary: primaryA, secondary: secondaryA } } of multiRobots) {
//// console.log(primaryA);
////}
////for ({ skills: { [|primary|], secondary } } of multiRobots) {
//// console.log([|primary|]);
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,23 @@
/// <reference path='fourslash.ts' />
////class A {
//// [|foo|]: string;
////}
////class B {
//// syntax1(a: A): void {
//// let { [|foo|] } = a;
//// }
//// syntax2(a: A): void {
//// let { [|foo|]: foo } = a;
//// }
//// syntax11(a: A): void {
//// let { [|foo|] } = a;
//// [|foo|] = "newString";
//// }
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,20 @@
/// <reference path='fourslash.ts' />
////interface I {
//// [|property1|]: number;
//// property2: string;
////}
////var elems: I[];
////
////var p2: number, property1: number;
////for (let { [|property1|]: p2 } = elems[0]; p2 < 100; p2++) {
////}
////for (let { [|property1|] } = elems[0]; p2 < 100; p2++) {
//// [|property1|] = p2;
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,19 @@
/// <reference path='fourslash.ts' />
////interface I {
//// [|property1|]: number;
//// property2: string;
////}
////var elems: I[];
////
////for (let { [|property1|] } of elems) {
//// [|property1|]++;
////}
////for (let { [|property1|]: p2 } of elems) {
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,10 @@
/// <reference path='fourslash.ts' />
////function f({[|a|]}: {[|a|]}) {
//// f({[|a|]});
////}
let ranges = test.ranges();
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,22 @@
/// <reference path='fourslash.ts' />
////interface MultiRobot {
//// name: string;
//// skills: {
//// [|primary|]: string;
//// secondary: string;
//// };
////}
////let multiRobots: MultiRobot[];
////for (let { skills: {[|primary|]: primaryA, secondary: secondaryA } } of multiRobots) {
//// console.log(primaryA);
////}
////for (let { skills: {[|primary|], secondary } } of multiRobots) {
//// console.log([|primary|]);
////}
let ranges = test.ranges()
for (let range of ranges) {
goTo.position(range.start);
verify.renameLocations(/*findInStrings*/ false, /*findInComments*/ false);
}

View File

@ -0,0 +1,18 @@
/// <reference path='fourslash.ts' />
// @Filename: a.ts
////export var /*1*/a;
// @Filename: b.ts
////import { /*2*/a } from './a';
////export { /*3*/a };
goTo.file("a.ts");
goTo.marker("1");
goTo.file("b.ts");
goTo.marker("2");
verify.referencesCountIs(3);
goTo.marker("3");
verify.referencesCountIs(3);