diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 6401c7ed87..ad6f1a811e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -1384,7 +1384,7 @@ namespace ts { // Export assignment in some sort of block construct bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node)); } - else if (boundExpression.kind === SyntaxKind.Identifier) { + else if (boundExpression.kind === SyntaxKind.Identifier && node.kind === SyntaxKind.ExportAssignment) { // An export default clause with an identifier exports all meanings of that identifier declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes); } @@ -1444,8 +1444,16 @@ namespace ts { // Look up the function in the local scope, since prototype assignments should // follow the function declaration - const classId = ((node.left).expression).expression; - const funcSymbol = container.locals[classId.text]; + const leftSideOfAssignment = node.left as PropertyAccessExpression; + const classPrototype = leftSideOfAssignment.expression as PropertyAccessExpression; + const constructorFunction = classPrototype.expression as Identifier; + + // Fix up parent pointers since we're going to use these nodes before we bind into them + leftSideOfAssignment.parent = node; + constructorFunction.parent = classPrototype; + classPrototype.parent = leftSideOfAssignment; + + const funcSymbol = container.locals[constructorFunction.text]; if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function)) { return; } @@ -1456,7 +1464,7 @@ namespace ts { } // Declare the method/property - declareSymbol(funcSymbol.members, funcSymbol, node.left, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, SymbolFlags.Property, SymbolFlags.PropertyExcludes); } function bindCallExpression(node: CallExpression) { diff --git a/tests/cases/fourslash/javaScriptModules13.ts b/tests/cases/fourslash/javaScriptModules13.ts index 4eed369836..cb3ef36783 100644 --- a/tests/cases/fourslash/javaScriptModules13.ts +++ b/tests/cases/fourslash/javaScriptModules13.ts @@ -23,4 +23,6 @@ verify.completionListContains('y'); verify.not.completionListContains('invisible'); edit.insert('x.'); -verify.completionListContains('a'); +verify.memberListContains('a', undefined, undefined, 'property'); +edit.insert('a.'); +verify.memberListContains('toFixed', undefined, undefined, 'method'); diff --git a/tests/cases/fourslash/javaScriptModules19.ts b/tests/cases/fourslash/javaScriptModules19.ts new file mode 100644 index 0000000000..91e2439dcc --- /dev/null +++ b/tests/cases/fourslash/javaScriptModules19.ts @@ -0,0 +1,26 @@ +/// + +// Assignments to 'module.exports' create an external module + +// @allowJs: true +// @Filename: myMod.js +//// var x = { a: 10 }; +//// module.exports = x; + +// @Filename: isGlobal.js +//// var y = 10; + +// @Filename: consumer.js +//// var x = require('myMod'); +//// /**/; + +goTo.file('consumer.js'); +goTo.marker(); + +verify.completionListContains('y'); +verify.not.completionListContains('invisible'); + +edit.insert('x.'); +verify.memberListContains('a', undefined, undefined, 'property'); +edit.insert('a.'); +verify.memberListContains('toFixed', undefined, undefined, 'method');