diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 46624fabbf1..80778789e7b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3461,11 +3461,14 @@ module ts { } function checkThisExpression(node: Node): Type { - var container = getThisContainerOrArrowFunction(node); + // Stop at the first arrow function so that we can + // tell whether 'this' needs to be captured. + var container = getThisContainer(node, /* includeArrowFunctions */ true); var needToCaptureLexicalThis = false; - // skip arrow functions - while (container.kind === SyntaxKind.ArrowFunction) { - container = getThisContainerOrArrowFunction(container); + + // Now skip arrow functions to get the "real" owner of 'this'. + if (container.kind === SyntaxKind.ArrowFunction) { + container = getThisContainer(container, /* includeArrowFunctions */ false); needToCaptureLexicalThis = true; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 288781db78f..e2d2bb3886b 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -407,13 +407,18 @@ module ts { } } - export function getThisContainerOrArrowFunction(node: Node): Node { + export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node { while (true) { node = node.parent; if (!node) { return node; } switch (node.kind) { + case SyntaxKind.ArrowFunction: + if (!includeArrowFunctions) { + continue; + } + // Fall through case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: case SyntaxKind.ModuleDeclaration: @@ -424,20 +429,11 @@ module ts { case SyntaxKind.SetAccessor: case SyntaxKind.EnumDeclaration: case SyntaxKind.SourceFile: - case SyntaxKind.ArrowFunction: return node; } } } - export function getThisContainer(node: Node): Node { - do { - node = getThisContainerOrArrowFunction(node); - } while (node.kind === SyntaxKind.ArrowFunction); - - return node; - } - export function hasRestParameters(s: SignatureDeclaration): boolean { return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0; } diff --git a/src/services/services.ts b/src/services/services.ts index ef9c8cf40c2..12f7e0ce24e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2629,7 +2629,7 @@ module ts { function getReferencesForThisKeyword(thisKeyword: Node, sourceFiles: SourceFile[]) { // Get the owner" of the 'this' keyword. - var thisContainer = getThisContainer(thisKeyword); + var thisContainer = getThisContainer(thisKeyword, /* includeArrowFunctions */ false); var searchSpaceNode: Node; @@ -2645,9 +2645,13 @@ module ts { searchSpaceNode = thisContainer.parent; // should be the owning class staticFlag &= thisContainer.flags break; + case SyntaxKind.SourceFile: + if (isExternalModule(thisContainer)) { + return undefined; + } + // Fall through case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: - case SyntaxKind.SourceFile: searchSpaceNode = thisContainer; break; default: @@ -2679,8 +2683,9 @@ module ts { return; } - // Get the owner" of the 'this' keyword. - var container = getThisContainer(node); + // Get the owner of the 'this' keyword. + // This *should* be a node that occurs somewhere within searchSpaceNode. + var container = getThisContainer(node, /* includeArrowFunctions */ false); switch (container.kind) { case SyntaxKind.Property: @@ -2702,7 +2707,7 @@ module ts { break; case SyntaxKind.SourceFile: // Add all 'this' keywords that belong to the top-level scope. - if (searchSpaceNode.kind === SyntaxKind.SourceFile) { + if (searchSpaceNode.kind === SyntaxKind.SourceFile && !isExternalModule(searchSpaceNode)) { result.push(getReferenceEntryFromNode(node)); } break; @@ -2970,21 +2975,7 @@ module ts { } else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { var operator = (parent).operator; - switch (operator) { - case SyntaxKind.AsteriskEqualsToken: - case SyntaxKind.SlashEqualsToken: - case SyntaxKind.PercentEqualsToken: - case SyntaxKind.MinusEqualsToken: - case SyntaxKind.LessThanLessThanEqualsToken: - case SyntaxKind.GreaterThanGreaterThanEqualsToken: - case SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken: - case SyntaxKind.BarEqualsToken: - case SyntaxKind.CaretEqualsToken: - case SyntaxKind.AmpersandEqualsToken: - case SyntaxKind.PlusEqualsToken: - case SyntaxKind.EqualsToken: - return true; - } + return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; } }