mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Support o.x = o.x || {} assignments in JS
Plus add tests for them
This commit is contained in:
@@ -4363,6 +4363,10 @@ namespace ts {
|
||||
// !!! (probably out of place, probably not the right function to call)
|
||||
return links.type = checkExpression(((declaration as VariableDeclaration).initializer as BinaryExpression).right);
|
||||
}
|
||||
if (isInJavaScriptFile(declaration) && isAssignmentOfDefaultedJavascriptContainerExpression(symbol)) {
|
||||
// !!! (probably out of place, probably not the right function to call)
|
||||
return links.type = checkExpression(((declaration.parent as BinaryExpression).right as BinaryExpression).right);
|
||||
}
|
||||
// Handle variable, parameter or property
|
||||
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
|
||||
return unknownType;
|
||||
|
||||
+26
-10
@@ -1504,16 +1504,32 @@ namespace ts {
|
||||
}
|
||||
|
||||
export function isDeclarationOfDefaultedJavascriptContainerExpression(s: Symbol) {
|
||||
if (s.valueDeclaration && isVariableDeclaration(s.valueDeclaration)) {
|
||||
return s.valueDeclaration.initializer &&
|
||||
isBinaryExpression(s.valueDeclaration.initializer) &&
|
||||
isIdentifier(s.valueDeclaration.initializer.left) &&
|
||||
isIdentifier(s.valueDeclaration.name) &&
|
||||
s.valueDeclaration.initializer.left.escapedText === s.valueDeclaration.name.escapedText &&
|
||||
isObjectLiteralExpression(s.valueDeclaration.initializer.right) &&
|
||||
s.valueDeclaration.initializer.right.properties.length === 0;
|
||||
}
|
||||
return false;
|
||||
return s.valueDeclaration &&
|
||||
isVariableDeclaration(s.valueDeclaration) &&
|
||||
s.valueDeclaration.initializer &&
|
||||
isBinaryExpression(s.valueDeclaration.initializer) &&
|
||||
isIdentifier(s.valueDeclaration.initializer.left) &&
|
||||
isIdentifier(s.valueDeclaration.name) &&
|
||||
s.valueDeclaration.initializer.left.escapedText === s.valueDeclaration.name.escapedText &&
|
||||
// TODO: Should still probably be isJavascriptContainerExpression
|
||||
isObjectLiteralExpression(s.valueDeclaration.initializer.right) &&
|
||||
s.valueDeclaration.initializer.right.properties.length === 0;
|
||||
}
|
||||
|
||||
export function isAssignmentOfDefaultedJavascriptContainerExpression(s: Symbol) {
|
||||
return s.valueDeclaration &&
|
||||
isPropertyAccessExpression(s.valueDeclaration) &&
|
||||
isBinaryExpression(s.valueDeclaration.parent) &&
|
||||
s.valueDeclaration.parent.right &&
|
||||
isBinaryExpression(s.valueDeclaration.parent.right) &&
|
||||
isPropertyAccessExpression(s.valueDeclaration.parent.right.left) &&
|
||||
isIdentifier(s.valueDeclaration.parent.right.left.expression) &&
|
||||
isPropertyAccessExpression(s.valueDeclaration.parent.left) &&
|
||||
isIdentifier(s.valueDeclaration.parent.left.expression) &&
|
||||
s.valueDeclaration.parent.right.left.expression.escapedText === s.valueDeclaration.parent.left.expression.escapedText &&
|
||||
s.valueDeclaration.parent.right.left.name.escapedText === s.valueDeclaration.parent.left.name.escapedText &&
|
||||
isObjectLiteralExpression(s.valueDeclaration.parent.right.right) &&
|
||||
s.valueDeclaration.parent.right.right.properties.length === 0;
|
||||
}
|
||||
|
||||
export function getRightMostAssignedExpression(node: Expression): Expression {
|
||||
|
||||
@@ -12,28 +12,43 @@ my.m = function() {
|
||||
|
||||
return 1;
|
||||
}
|
||||
my.p = {};
|
||||
>my.p : Symbol(p, Decl(a.js, 5, 1))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>p : Symbol(p, Decl(a.js, 5, 1))
|
||||
|
||||
my.n = 1;
|
||||
>my.n : Symbol(n, Decl(a.js, 6, 10))
|
||||
>my.n : Symbol(n, Decl(a.js, 5, 1))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>n : Symbol(n, Decl(a.js, 6, 10))
|
||||
>n : Symbol(n, Decl(a.js, 5, 1))
|
||||
|
||||
my.m
|
||||
my.o = {};
|
||||
>my.o : Symbol(o, Decl(a.js, 6, 9))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>o : Symbol(o, Decl(a.js, 6, 9))
|
||||
|
||||
my.possible = my.possible || {};
|
||||
>my.possible : Symbol(possible, Decl(a.js, 7, 10))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>possible : Symbol(possible, Decl(a.js, 7, 10))
|
||||
>my.possible : Symbol(possible, Decl(a.js, 7, 10))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>possible : Symbol(possible, Decl(a.js, 7, 10))
|
||||
|
||||
my.m;
|
||||
>my.m : Symbol(m, Decl(a.js, 2, 18))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>m : Symbol(m, Decl(a.js, 2, 18))
|
||||
|
||||
my.p
|
||||
>my.p : Symbol(p, Decl(a.js, 5, 1))
|
||||
my.o;
|
||||
>my.o : Symbol(o, Decl(a.js, 6, 9))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>p : Symbol(p, Decl(a.js, 5, 1))
|
||||
>o : Symbol(o, Decl(a.js, 6, 9))
|
||||
|
||||
my.n
|
||||
>my.n : Symbol(n, Decl(a.js, 6, 10))
|
||||
my.n;
|
||||
>my.n : Symbol(n, Decl(a.js, 5, 1))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>n : Symbol(n, Decl(a.js, 6, 10))
|
||||
>n : Symbol(n, Decl(a.js, 5, 1))
|
||||
|
||||
my.possible;
|
||||
>my.possible : Symbol(possible, Decl(a.js, 7, 10))
|
||||
>my : Symbol(my, Decl(a.js, 2, 3), Decl(a.js, 2, 18))
|
||||
>possible : Symbol(possible, Decl(a.js, 7, 10))
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,47 +2,65 @@
|
||||
// TODO: JSDoc would provide a contextual type, so ... I should test that
|
||||
// TODO: Try initializer of function or class I guess (though classes aren't context sensitive)
|
||||
var my = my || {};
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>my || {} : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>{} : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>my || {} : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>{} : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
|
||||
my.m = function() {
|
||||
>my.m = function() { return 1;} : () => number
|
||||
>my.m : () => number
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>m : () => number
|
||||
>function() { return 1;} : () => number
|
||||
|
||||
return 1;
|
||||
>1 : 1
|
||||
}
|
||||
my.p = {};
|
||||
>my.p = {} : { [x: string]: any; }
|
||||
>my.p : { [x: string]: any; }
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>p : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
my.n = 1;
|
||||
>my.n = 1 : 1
|
||||
>my.n : number
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>n : number
|
||||
>1 : 1
|
||||
|
||||
my.m
|
||||
my.o = {};
|
||||
>my.o = {} : { [x: string]: any; }
|
||||
>my.o : { [x: string]: any; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>o : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
my.possible = my.possible || {};
|
||||
>my.possible = my.possible || {} : { [x: string]: any; }
|
||||
>my.possible : { [x: string]: any; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>possible : { [x: string]: any; }
|
||||
>my.possible || {} : { [x: string]: any; }
|
||||
>my.possible : { [x: string]: any; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>possible : { [x: string]: any; }
|
||||
>{} : { [x: string]: any; }
|
||||
|
||||
my.m;
|
||||
>my.m : () => number
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>m : () => number
|
||||
|
||||
my.p
|
||||
>my.p : { [x: string]: any; }
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>p : { [x: string]: any; }
|
||||
my.o;
|
||||
>my.o : { [x: string]: any; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>o : { [x: string]: any; }
|
||||
|
||||
my.n
|
||||
my.n;
|
||||
>my.n : number
|
||||
>my : { [x: string]: any; m: () => number; p: { [x: string]: any; }; n: number; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>n : number
|
||||
|
||||
my.possible;
|
||||
>my.possible : { [x: string]: any; }
|
||||
>my : { [x: string]: any; m: () => number; n: number; o: { [x: string]: any; }; possible: { [x: string]: any; }; }
|
||||
>possible : { [x: string]: any; }
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user