This commit is contained in:
Ryan Cavanaugh 2015-11-20 10:59:13 -08:00
parent eaeeb1f762
commit fb83ee0a30
4 changed files with 16 additions and 68 deletions

View File

@ -635,7 +635,6 @@ namespace ts {
function bindAnonymousDeclaration(node: Declaration, symbolFlags: SymbolFlags, name: string) {
let symbol = createSymbol(symbolFlags, name);
addDeclarationToSymbol(symbol, node, symbolFlags);
return symbol;
}
function bindBlockScopedDeclaration(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
@ -889,6 +888,11 @@ namespace ts {
case SpecialPropertyAssignmentKind.ThisProperty:
bindThisPropertyAssignment(<BinaryExpression>node);
break;
case SpecialPropertyAssignmentKind.None:
// Nothing to do
break;
default:
Debug.fail("Unknown special property assignment kind");
}
}
return checkStrictModeBinaryExpression(<BinaryExpression>node);
@ -1080,19 +1084,19 @@ namespace ts {
// The function is now a constructor rather than a normal function
if (!funcSymbol.inferredConstructor) {
// Have the binder set up all the related class symbols for us
declareSymbol(container.locals, funcSymbol, funcSymbol.valueDeclaration, SymbolFlags.Class, SymbolFlags.None);
// funcSymbol.flags = (funcSymbol.flags | SymbolFlags.Class) & ~SymbolFlags.Function;
funcSymbol.members = funcSymbol.members || {};
// funcSymbol.members = funcSymbol.members || {};
funcSymbol.members["__constructor"] = funcSymbol;
funcSymbol.inferredConstructor = true;
}
// Declare the 'prototype' member of the function
let prototypeSymbol = declareSymbol(funcSymbol.exports, funcSymbol, <PropertyAccessExpression>(<PropertyAccessExpression>node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None);
// Get the exports of the class so we can add the method to it
let funcExports = declareSymbol(funcSymbol.exports, funcSymbol, <PropertyAccessExpression>(<PropertyAccessExpression>node.left).expression, SymbolFlags.ObjectLiteral | SymbolFlags.Property, SymbolFlags.None);
// Declare the property on the prototype symbol
declareSymbol(prototypeSymbol.members, prototypeSymbol, <PropertyAccessExpression>node.left, SymbolFlags.Method, SymbolFlags.None);
// and on the class type
// Declare the method
declareSymbol(funcExports.members, funcExports, <PropertyAccessExpression>node.left, SymbolFlags.Method, SymbolFlags.None);
// and on the members of the function so it appears in 'prototype'
declareSymbol(funcSymbol.members, funcSymbol, <PropertyAccessExpression>node.left, SymbolFlags.Method, SymbolFlags.PropertyExcludes);
}

View File

@ -2577,9 +2577,11 @@ namespace ts {
return links.type = checkExpression((<BinaryExpression>declaration).right);
}
if (declaration.kind === SyntaxKind.PropertyAccessExpression) {
// Declarations only exist for property access expressions for certain
// special assignment kinds
if (declaration.parent.kind === SyntaxKind.BinaryExpression) {
// Handle exports.p = expr or this.p = expr or className.prototype.method = expr
return links.type = checkExpression((<BinaryExpression>declaration.parent).right);
return links.type = checkExpressionCached((<BinaryExpression>declaration.parent).right);
}
else {
// Declaration for className.prototype in inferred JS class
@ -3860,6 +3862,7 @@ namespace ts {
break;
case SyntaxKind.PropertyAccessExpression:
// Inferred class method
result = getSignaturesOfType(checkExpressionCached((<BinaryExpression>node.parent).right), SignatureKind.Call);
break;
}

View File

@ -1093,64 +1093,6 @@ namespace ts {
return SpecialPropertyAssignmentKind.None;
}
/**
* Returns true if the node is an assignment to a property on the identifier 'exports'.
* This function does not test if the node is in a JavaScript file or not.
*/
export function isExportsPropertyAssignment(expression: Node): boolean {
// of the form 'exports.name = expr' where 'name' and 'expr' are arbitrary
return isInJavaScriptFile(expression) &&
(expression.kind === SyntaxKind.BinaryExpression) &&
((<BinaryExpression>expression).operatorToken.kind === SyntaxKind.EqualsToken) &&
((<BinaryExpression>expression).left.kind === SyntaxKind.PropertyAccessExpression) &&
((<PropertyAccessExpression>(<BinaryExpression>expression).left).expression.kind === SyntaxKind.Identifier) &&
((<Identifier>((<PropertyAccessExpression>(<BinaryExpression>expression).left).expression)).text === "exports");
}
/**
* Returns true if the node is an assignment to the property access expression 'module.exports'.
* This function does not test if the node is in a JavaScript file or not.
*/
export function isModuleExportsAssignment(expression: Node): boolean {
// of the form 'module.exports = expr' where 'expr' is arbitrary
return isInJavaScriptFile(expression) &&
(expression.kind === SyntaxKind.BinaryExpression) &&
((<BinaryExpression>expression).operatorToken.kind === SyntaxKind.EqualsToken) &&
((<BinaryExpression>expression).left.kind === SyntaxKind.PropertyAccessExpression) &&
((<PropertyAccessExpression>(<BinaryExpression>expression).left).expression.kind === SyntaxKind.Identifier) &&
((<Identifier>((<PropertyAccessExpression>(<BinaryExpression>expression).left).expression)).text === "module") &&
((<PropertyAccessExpression>(<BinaryExpression>expression).left).name.text === "exports");
}
/**
* Returns true if this expression is an assignment to the given named property
*/
function isAssignmentToProperty(expression: Node, name?: string): expression is BinaryExpression {
return (expression.kind === SyntaxKind.BinaryExpression) &&
((<BinaryExpression>expression).operatorToken.kind === SyntaxKind.EqualsToken) &&
isNamedPropertyAccess((<BinaryExpression>expression).left, name);
}
/**
* Returns true if this expression is a PropertyAccessExpression where the property name is the provided name
*/
function isNamedPropertyAccess(expression: Node, name?: string): expression is PropertyAccessExpression {
return expression.kind === SyntaxKind.PropertyAccessExpression &&
(!name || (<PropertyAccessExpression>expression).name.text === name);
}
/**
* Returns true if the node is an assignment in the form 'id1.prototype.id2 = expr' where id1 and id2
* are any identifier.
* This function does not test if the node is in a JavaScript file or not.
*/
export function isPrototypePropertyAssignment(expression: Node): expression is BinaryExpression {
return isAssignmentToProperty(expression) &&
isNamedPropertyAccess(expression.left) &&
isNamedPropertyAccess((<PropertyAccessExpression>expression.left).expression, "prototype") &&
(<PropertyAccessExpression>(<PropertyAccessExpression>expression.left).expression).expression.kind === SyntaxKind.Identifier;
}
export function getExternalModuleName(node: Node): Expression {
if (node.kind === SyntaxKind.ImportDeclaration) {
return (<ImportDeclaration>node).moduleSpecifier;

View File

@ -23,7 +23,6 @@ verify.completionListContains('qua', undefined, undefined, 'warning');
// Check members of function.prototype
edit.insert('prototype.');
debug.printMemberListMembers();
verify.completionListContains('foo', undefined, undefined, 'method');
verify.completionListContains('bar', undefined, undefined, 'method');
verify.completionListContains('qua', undefined, undefined, 'warning');