Skip to content

Commit cbc112a

Browse files
committed
Support this.prop = expr; assignments as declarations for ES6 JS classes
1 parent 32178ac commit cbc112a

File tree

5 files changed

+91
-0
lines changed

5 files changed

+91
-0
lines changed

src/compiler/binder.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1478,6 +1478,14 @@ namespace ts {
14781478
// It's acceptable for multiple 'this' assignments of the same identifier to occur
14791479
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
14801480
}
1481+
else if (container.kind === SyntaxKind.Constructor && isInJavaScriptFile(node)) {
1482+
// this.foo assignment in a JavaScript class
1483+
// Bind this property to the containing class
1484+
const saveContainer = container;
1485+
container = container.parent;
1486+
bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None);
1487+
container = saveContainer;
1488+
}
14811489
}
14821490

14831491
function bindPrototypePropertyAssignment(node: BinaryExpression) {

src/compiler/checker.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8037,6 +8037,11 @@ namespace ts {
80378037
const binaryExpression = <BinaryExpression>node.parent;
80388038
const operator = binaryExpression.operatorToken.kind;
80398039
if (operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {
8040+
// Don't do this for special property assignments to avoid circularity
8041+
if (getSpecialPropertyAssignmentKind(binaryExpression) !== SpecialPropertyAssignmentKind.None) {
8042+
return undefined;
8043+
}
8044+
80408045
// In an assignment expression, the right operand is contextually typed by the type of the left operand.
80418046
if (node === binaryExpression.right) {
80428047
return checkExpression(binaryExpression.left);
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
///<reference path="fourslash.ts" />
2+
3+
// Classes have their shape inferred from assignments
4+
// to properties of 'this' in the constructor
5+
6+
// @allowNonTsExtensions: true
7+
// @Filename: Foo.js
8+
//// class Foo {
9+
//// constructor() {
10+
//// this.bar = 'world';
11+
//// this.thing = 42;
12+
//// this.union = 'foo';
13+
//// this.union = 100;
14+
//// }
15+
//// }
16+
//// var x = new Foo();
17+
//// x/**/
18+
19+
20+
goTo.marker();
21+
edit.insert('.');
22+
verify.completionListContains("bar", /*displayText*/ undefined, /*documentation*/ undefined, "property");
23+
verify.completionListContains("thing", /*displayText*/ undefined, /*documentation*/ undefined, "property");
24+
verify.completionListContains("union", /*displayText*/ undefined, /*documentation*/ undefined, "property");
25+
26+
edit.insert('bar.');
27+
verify.completionListContains("substr", /*displayText*/ undefined, /*documentation*/ undefined, "method");
28+
29+
edit.backspace('bar.'.length);
30+
31+
edit.insert('union.');
32+
verify.completionListContains("toString", /*displayText*/ undefined, /*documentation*/ undefined, "method");
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
///<reference path="fourslash.ts" />
2+
3+
// In an inferred class, we can rename successfully
4+
5+
// @allowNonTsExtensions: true
6+
// @Filename: Foo.js
7+
//// class Foo {
8+
//// constructor() {
9+
//// this.[|union|] = 'foo';
10+
//// this./*1*/[|union|] = 100;
11+
//// }
12+
//// method() { return this./*2*/[|union|]; }
13+
//// }
14+
//// var x = new Foo();
15+
//// x./*3*/[|union|];
16+
17+
goTo.marker('1');
18+
verify.renameLocations(/*findInStrings*/false, /*findInComments*/false);
19+
goTo.marker('2');
20+
verify.renameLocations(/*findInStrings*/false, /*findInComments*/false);
21+
goTo.marker('3');
22+
verify.renameLocations(/*findInStrings*/false, /*findInComments*/false);
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
///<reference path="fourslash.ts" />
2+
3+
// In an inferred class, we can to-to-def successfully
4+
5+
// @allowNonTsExtensions: true
6+
// @Filename: Foo.js
7+
//// class Foo {
8+
//// constructor() {
9+
//// /*dst1*/this.alpha = 10;
10+
//// /*dst2*/this.beta = 'gamma';
11+
//// }
12+
//// method() { return this.alpha; }
13+
//// }
14+
//// var x = new Foo();
15+
//// x.alpha/*src1*/;
16+
//// x.beta/*src2*/;
17+
18+
goTo.marker('src1');
19+
goTo.definition();
20+
verify.caretAtMarker('dst1');
21+
22+
goTo.marker('src2');
23+
goTo.definition();
24+
verify.caretAtMarker('dst2');

0 commit comments

Comments
 (0)