Merge pull request #9088 from Microsoft/add-members-to-variable-declarations-initialised-with-function-expressions

Add members to variable declarations initialised with function expressions
This commit is contained in:
Nathan Shively-Sanders
2016-06-14 11:37:36 -07:00
committed by GitHub
4 changed files with 36 additions and 3 deletions
+1 -1
View File
@@ -1961,7 +1961,7 @@ namespace ts {
classPrototype.parent = leftSideOfAssignment;
const funcSymbol = container.locals[constructorFunction.text];
if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function)) {
if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function || isDeclarationOfFunctionExpression(funcSymbol))) {
return;
}
+6 -2
View File
@@ -11495,8 +11495,12 @@ namespace ts {
// When resolved signature is a call signature (and not a construct signature) the result type is any, unless
// the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations
// in a JS file
const funcSymbol = checkExpression(node.expression).symbol;
if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function)) {
// Note:JS inferred classes might come from a variable declaration instead of a function declaration.
// In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration.
const funcSymbol = node.expression.kind === SyntaxKind.Identifier ?
getResolvedSymbol(node.expression as Identifier) :
checkExpression(node.expression).symbol;
if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function || isDeclarationOfFunctionExpression(funcSymbol))) {
return getInferredClassType(funcSymbol);
}
else if (compilerOptions.noImplicitAny) {
+12
View File
@@ -1264,6 +1264,18 @@ namespace ts {
return charCode === CharacterCodes.singleQuote || charCode === CharacterCodes.doubleQuote;
}
/**
* Returns true if the node is a variable declaration whose initializer is a function expression.
* This function does not test if the node is in a JavaScript file or not.
*/
export function isDeclarationOfFunctionExpression(s: Symbol) {
if (s.valueDeclaration && s.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
const declaration = s.valueDeclaration as VariableDeclaration;
return declaration.initializer && declaration.initializer.kind === SyntaxKind.FunctionExpression;
}
return false;
}
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
/// assignments we treat as special in the binder
export function getSpecialPropertyAssignmentKind(expression: Node): SpecialPropertyAssignmentKind {
@@ -0,0 +1,17 @@
/// <reference path="fourslash.ts" />
// @allowJs: true
// @Filename: something.js
////var C = function () { }
/////**
//// * The prototype method.
//// * @param {string} a Parameter definition.
//// */
////function f(a) {}
////C.prototype.m = f;
////
////var x = new C();
////x/*1*/./*2*/m();
goTo.marker('1');
verify.quickInfoIs('var x: {\n m: (a: string) => void;\n}');
goTo.marker('2');
verify.completionListContains('m', '(property) C.m: (a: string) => void', 'The prototype method.');