Merge pull request #16031 from Microsoft/isWriteAccess

findAllReferences: Make "isWriteAccess" handle special declaration kinds
This commit is contained in:
Andy 2017-05-23 11:11:18 -07:00 committed by GitHub
commit 23b2545586
18 changed files with 51 additions and 36 deletions

View file

@ -12750,7 +12750,7 @@ namespace ts {
function getContextualTypeForBinaryOperand(node: Expression): Type {
const binaryExpression = <BinaryExpression>node.parent;
const operator = binaryExpression.operatorToken.kind;
if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
if (isAssignmentOperator(operator)) {
// Don't do this for special property assignments to avoid circularity
if (getSpecialPropertyAssignmentKind(binaryExpression) !== SpecialPropertyAssignmentKind.None) {
return undefined;
@ -17305,7 +17305,7 @@ namespace ts {
}
function checkAssignmentOperator(valueType: Type): void {
if (produceDiagnostics && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
if (produceDiagnostics && isAssignmentOperator(operator)) {
// TypeScript 1.0 spec (April 2014): 4.17
// An assignment of the form
// VarExpr = ValueExpr

View file

@ -1785,6 +1785,23 @@ namespace ts {
}
}
/* @internal */
// See GH#16030
export function isAnyDeclarationName(name: Node): boolean {
switch (name.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
if (isDeclaration(name.parent)) {
return name.parent.name === name;
}
const binExp = name.parent.parent;
return isBinaryExpression(binExp) && getSpecialPropertyAssignmentKind(binExp) !== SpecialPropertyAssignmentKind.None && getNameOfDeclaration(binExp) === name;
default:
return false;
}
}
export function isLiteralComputedPropertyDeclarationName(node: Node) {
return (node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NumericLiteral) &&
node.parent.kind === SyntaxKind.ComputedPropertyName &&

View file

@ -176,7 +176,7 @@ namespace ts.FindAllReferences {
fileName: node.getSourceFile().fileName,
textSpan: getTextSpan(node),
isWriteAccess: isWriteAccess(node),
isDefinition: isDeclarationName(node) || isLiteralComputedPropertyDeclarationName(node),
isDefinition: isAnyDeclarationName(node) || isLiteralComputedPropertyDeclarationName(node),
isInString
};
}
@ -242,22 +242,20 @@ namespace ts.FindAllReferences {
/** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
function isWriteAccess(node: Node): boolean {
if (node.kind === SyntaxKind.Identifier && isDeclarationName(node)) {
if (isAnyDeclarationName(node)) {
return true;
}
const parent = node.parent;
if (parent) {
if (parent.kind === SyntaxKind.PostfixUnaryExpression || parent.kind === SyntaxKind.PrefixUnaryExpression) {
const { parent } = node;
switch (parent && parent.kind) {
case SyntaxKind.PostfixUnaryExpression:
case SyntaxKind.PrefixUnaryExpression:
return true;
}
else if (parent.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>parent).left === node) {
const operator = (<BinaryExpression>parent).operatorToken.kind;
return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment;
}
case SyntaxKind.BinaryExpression:
return (<BinaryExpression>parent).left === node && isAssignmentOperator((<BinaryExpression>parent).operatorToken.kind);
default:
return false;
}
return false;
}
}

View file

@ -6,7 +6,7 @@
// @Filename: /b.ts
/////// <reference types="[|foo|]" />
////import { x } from "[|foo|]";
////declare module "[|{| "isDefinition": true |}foo|]" {}
////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}foo|]" {}
verify.noErrors();

View file

@ -1,5 +1,5 @@
/// <reference path='fourslash.ts' />
////let o = { [|{| "isDefinition": true |}1|]: 12 };
////let o = { [|{| "isWriteAccess": true, "isDefinition": true |}1|]: 12 };
////let y = o[[|1|]];
const ranges = test.ranges();

View file

@ -1,5 +1,5 @@
/// <reference path='fourslash.ts' />
////let o = { "[|{| "isDefinition": true |}x|]": 12 };
////let o = { "[|{| "isWriteAccess": true, "isDefinition": true |}x|]": 12 };
////let y = o.[|x|];
const ranges = test.ranges();

View file

@ -12,7 +12,7 @@
////function blah2() { container["[|searchProp|]"] };
// @Filename: redeclaration.ts
////container = { "[|{| "isDefinition": true |}searchProp|]" : 18 };
////container = { "[|{| "isWriteAccess": true, "isDefinition": true |}searchProp|]" : 18 };
const ranges = test.ranges();
const [r0, r1, r2, r3] = ranges;

View file

@ -3,7 +3,7 @@
// Ensure BloomFilter building logic is correct, by having one reference per file
// @Filename: declaration.ts
////var container = { [|{| "isDefinition": true |}42|]: 1 };
////var container = { [|{| "isWriteAccess": true, "isDefinition": true |}42|]: 1 };
// @Filename: expression.ts
////function blah() { return (container[[|42|]]) === 2; };
@ -12,7 +12,7 @@
////function blah2() { container["[|42|]"] };
// @Filename: redeclaration.ts
////container = { "[|{| "isDefinition": true |}42|]" : 18 };
////container = { "[|{| "isWriteAccess": true, "isDefinition": true |}42|]" : 18 };
const ranges = test.ranges();
const [r0, r1, r2, r3] = ranges;

View file

@ -4,7 +4,7 @@
// @Filename: declaration.ts
////enum Test { "[|{| "isDefinition": true |}42|]" = 1 };
////enum Test { "[|{| "isWriteAccess": true, "isDefinition": true |}42|]" = 1 };
// @Filename: expression.ts
////(Test[[|42|]]);

View file

@ -1,10 +1,10 @@
/// <reference path='fourslash.ts'/>
////declare module "[|{| "isDefinition": true |}foo|]" {
////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}foo|]" {
//// var [|{| "isWriteAccess": true, "isDefinition": true |}f|]: number;
////}
////
////declare module "[|{| "isDefinition": true |}bar|]" {
////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}bar|]" {
//// export import [|{| "isWriteAccess": true, "isDefinition": true |}foo|] = require("[|foo|]");
//// var f2: typeof [|foo|].[|f|];
////}

View file

@ -2,8 +2,8 @@
////enum E {
//// [|{| "isWriteAccess": true, "isDefinition": true |}value1|] = 1,
//// "[|{| "isDefinition": true |}value2|]" = [|value1|],
//// [|{| "isDefinition": true |}111|] = 11
//// "[|{| "isWriteAccess": true, "isDefinition": true |}value2|]" = [|value1|],
//// [|{| "isWriteAccess": true, "isDefinition": true |}111|] = 11
////}
////
////E.[|value1|];

View file

@ -3,7 +3,7 @@
// Global interface reference.
// @Filename: referencesForGlobals_1.ts
////declare module "[|{| "isDefinition": true |}foo|]" {
////declare module "[|{| "isWriteAccess": true, "isDefinition": true |}foo|]" {
//// var f: number;
////}

View file

@ -1,13 +1,13 @@
/// <reference path='fourslash.ts'/>
////class Foo {
//// public [|{| "isDefinition": true |}12|]: any;
//// public [|{| "isWriteAccess": true, "isDefinition": true |}12|]: any;
////}
////
////var x: Foo;
////x[[|12|]];
////x = { "[|{| "isDefinition": true |}12|]": 0 };
////x = { [|{| "isDefinition": true |}12|]: 0 };
////x = { "[|{| "isWriteAccess": true, "isDefinition": true |}12|]": 0 };
////x = { [|{| "isWriteAccess": true, "isDefinition": true |}12|]: 0 };
//verify.singleReferenceGroup("(property) Foo[12]: any");
const ranges = test.ranges();

View file

@ -1,13 +1,13 @@
/// <reference path='fourslash.ts'/>
////class Foo {
//// public "[|{| "isDefinition": true |}ss|]": any;
//// public "[|{| "isWriteAccess": true, "isDefinition": true |}ss|]": any;
////}
////
////var x: Foo;
////x.[|ss|];
////x["[|ss|]"];
////x = { "[|{| "isDefinition": true |}ss|]": 0 };
////x = { "[|{| "isWriteAccess": true, "isDefinition": true |}ss|]": 0 };
////x = { [|{| "isWriteAccess": true, "isDefinition": true |}ss|]: 0 };
const ranges = test.ranges();

View file

@ -1,7 +1,7 @@
/// <reference path='fourslash.ts'/>
////class Foo {
//// "[|{| "isDefinition": true |}blah|]"() { return 0; }
//// "[|{| "isWriteAccess": true, "isDefinition": true |}blah|]"() { return 0; }
////}
////
////var x: Foo;

View file

@ -1,8 +1,8 @@
/// <reference path='fourslash.ts'/>
////class Foo2 {
//// get "[|{| "isDefinition": true |}42|]"() { return 0; }
//// set [|{| "isDefinition": true |}42|](n) { }
//// get "[|{| "isWriteAccess": true, "isDefinition": true |}42|]"() { return 0; }
//// set [|{| "isWriteAccess": true, "isDefinition": true |}42|](n) { }
////}
////
////var y: Foo2;

View file

@ -1,6 +1,6 @@
/// <reference path='fourslash.ts'/>
////var x = { "[|{| "isDefinition": true |}someProperty|]": 0 }
////var x = { "[|{| "isWriteAccess": true, "isDefinition": true |}someProperty|]": 0 }
////x["[|someProperty|]"] = 3;
////x.[|someProperty|] = 5;

View file

@ -2,7 +2,7 @@
// @allowJs: true
// @Filename: a.js
////exports.[|area|] = function (r) { return r * r; }
////exports.[|{| "isWriteAccess": true, "isDefinition": true |}area|] = function (r) { return r * r; }
// @Filename: b.js
////var mod = require('./a');