diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 780e530f497..80778789e7b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3449,29 +3449,6 @@ module ts { return getTypeOfSymbol(getExportSymbolOfValueSymbolIfExported(symbol)); } - function getThisContainer(node: Node): Node { - while (true) { - node = node.parent; - if (!node) { - return node; - } - switch (node.kind) { - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.FunctionExpression: - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.Property: - case SyntaxKind.Method: - case SyntaxKind.Constructor: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.SourceFile: - case SyntaxKind.ArrowFunction: - return node; - } - } - } - function captureLexicalThis(node: Node, container: Node): void { var classNode = container.parent && container.parent.kind === SyntaxKind.ClassDeclaration ? container.parent : undefined; getNodeLinks(node).flags |= NodeCheckFlags.LexicalThis; @@ -3484,11 +3461,14 @@ module ts { } function checkThisExpression(node: Node): Type { - var container = getThisContainer(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 = getThisContainer(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 05d1dddfccf..e2d2bb3886b 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -407,6 +407,33 @@ module ts { } } + 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: + case SyntaxKind.Property: + case SyntaxKind.Method: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.SourceFile: + 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 04451086ff8..12f7e0ce24e 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2146,7 +2146,8 @@ module ts { return undefined; } - if (node.kind === SyntaxKind.Identifier || isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { + if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || + isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) { return getReferencesForNode(node, [sourceFile]); } @@ -2243,7 +2244,7 @@ module ts { } // Ordinary case: just highlight the keyword. - result.push(keywordToReferenceEntry(keywords[i])); + result.push(getReferenceEntryFromNode(keywords[i])); } return result; @@ -2262,7 +2263,7 @@ module ts { pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword); }); - return map(keywords, keywordToReferenceEntry); + return map(keywords, getReferenceEntryFromNode); } function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[] { @@ -2278,7 +2279,7 @@ module ts { pushKeywordIf(keywords, tryStatement.finallyBlock.getFirstToken(), SyntaxKind.FinallyKeyword); } - return map(keywords, keywordToReferenceEntry); + return map(keywords, getReferenceEntryFromNode); } function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement) { @@ -2314,7 +2315,7 @@ module ts { }); }); - return map(keywords, keywordToReferenceEntry); + return map(keywords, getReferenceEntryFromNode); } function getBreakStatementOccurences(breakStatement: BreakOrContinueStatement): ReferenceEntry[]{ @@ -2363,10 +2364,6 @@ module ts { return false; } - - function keywordToReferenceEntry(keyword: Node): ReferenceEntry { - return new ReferenceEntry(filename, TypeScript.TextSpan.fromBounds(keyword.getStart(), keyword.end), /* isWriteAccess */ false); - } } function getReferencesAtPosition(filename: string, position: number): ReferenceEntry[] { @@ -2381,6 +2378,7 @@ module ts { } if (node.kind !== SyntaxKind.Identifier && + node.kind !== SyntaxKind.ThisKeyword && !isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && !isNameOfExternalModuleImportOrDeclaration(node)) { return undefined; @@ -2396,7 +2394,7 @@ module ts { var labelDefinition = getTargetLabel((node.parent), (node).text); // if we have a label definition, look within its statement for references, if not, then // the label is undefined, just return a set of one for the current node. - return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : [getReferenceEntry(node)]; + return labelDefinition ? getLabelReferencesInNode(labelDefinition.parent, labelDefinition) : [getReferenceEntryFromNode(node)]; } else { // it is a label definition and not a target, search within the parent labeledStatement @@ -2404,13 +2402,17 @@ module ts { } } + if (node.kind === SyntaxKind.ThisKeyword) { + return getReferencesForThisKeyword(node, sourceFiles); + } + var symbol = typeInfoResolver.getSymbolInfo(node); // Could not find a symbol e.g. unknown identifier if (!symbol) { // Even if we did not find a symbol, we have an identifer, so there is at least - // one reference that we know of. return than instead of undefined. - return [getReferenceEntry(node)]; + // one reference that we know of. return that instead of undefined. + return [getReferenceEntryFromNode(node)]; } // the symbol was an internal symbol and does not have a declaration e.g.undefined symbol @@ -2554,7 +2556,7 @@ module ts { // Only pick labels that are either the target label, or have a target that is the target label if (node === targetLabel || (isJumpStatementTarget(node) && getTargetLabel(node, labelName) === targetLabel)) { - result.push(getReferenceEntry(node)); + result.push(getReferenceEntryFromNode(node)); } }); return result; @@ -2619,7 +2621,96 @@ module ts { } if (isRelatableToSearchSet(searchSymbols, referenceSymbol, referenceLocation)) { - result.push(getReferenceEntry(referenceLocation)); + result.push(getReferenceEntryFromNode(referenceLocation)); + } + }); + } + } + + function getReferencesForThisKeyword(thisKeyword: Node, sourceFiles: SourceFile[]) { + // Get the owner" of the 'this' keyword. + var thisContainer = getThisContainer(thisKeyword, /* includeArrowFunctions */ false); + + var searchSpaceNode: Node; + + // Whether 'this' occurs in a static context within a class; + var staticFlag = NodeFlags.Static; + + switch (thisContainer.kind) { + case SyntaxKind.Property: + case SyntaxKind.Method: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + 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: + searchSpaceNode = thisContainer; + break; + default: + return undefined; + } + + var result: ReferenceEntry[] = []; + + if (searchSpaceNode.kind === SyntaxKind.SourceFile) { + forEach(sourceFiles, sourceFile => { + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", sourceFile.getStart(), sourceFile.getEnd()); + getThisReferencesInFile(sourceFile, sourceFile, possiblePositions, result); + }); + } + else { + var sourceFile = searchSpaceNode.getSourceFile(); + var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "this", searchSpaceNode.getStart(), searchSpaceNode.getEnd()); + getThisReferencesInFile(sourceFile, searchSpaceNode, possiblePositions, result); + } + + return result; + + function getThisReferencesInFile(sourceFile: SourceFile, searchSpaceNode: Node, possiblePositions: number[], result: ReferenceEntry[]): void { + forEach(possiblePositions, position => { + cancellationToken.throwIfCancellationRequested(); + + var node = getNodeAtPosition(sourceFile, position); + if (!node || node.kind !== SyntaxKind.ThisKeyword) { + return; + } + + // 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: + case SyntaxKind.Method: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + // Make sure the container belongs to the same class + // and has the appropriate static modifier from the original container. + if (searchSpaceNode.symbol === container.parent.symbol && (container.flags & NodeFlags.Static) === staticFlag) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + if (searchSpaceNode.symbol === container.symbol) { + result.push(getReferenceEntryFromNode(node)); + } + break; + case SyntaxKind.SourceFile: + // Add all 'this' keywords that belong to the top-level scope. + if (searchSpaceNode.kind === SyntaxKind.SourceFile && !isExternalModule(searchSpaceNode)) { + result.push(getReferenceEntryFromNode(node)); + } + break; } }); } @@ -2721,18 +2812,6 @@ module ts { return undefined; } - function getReferenceEntry(node: Node): ReferenceEntry { - var start = node.getStart(); - var end = node.getEnd(); - - if (node.kind === SyntaxKind.StringLiteral) { - start += 1; - end -= 1; - } - - return new ReferenceEntry(node.getSourceFile().filename, TypeScript.TextSpan.fromBounds(start, end), isWriteAccess(node)); - } - function getMeaningFromDeclaration(node: Declaration): SearchMeaning { switch (node.kind) { case SyntaxKind.Parameter: @@ -2869,40 +2948,38 @@ module ts { } return meaning; } + } - /// A node is considedered a writeAccess iff it is a name of a declaration or a target of an assignment - function isWriteAccess(node: Node): boolean { - if (node.kind === SyntaxKind.Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName(node)) { + function getReferenceEntryFromNode(node: Node): ReferenceEntry { + var start = node.getStart(); + var end = node.getEnd(); + + if (node.kind === SyntaxKind.StringLiteral) { + start += 1; + end -= 1; + } + + return new ReferenceEntry(node.getSourceFile().filename, TypeScript.TextSpan.fromBounds(start, end), isWriteAccess(node)); + } + + /// A node is considedered a writeAccess iff it is a name of a declaration or a target of an assignment + function isWriteAccess(node: Node): boolean { + if (node.kind === SyntaxKind.Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName(node)) { + return true; + } + + var parent = node.parent; + if (parent) { + if (parent.kind === SyntaxKind.PostfixOperator || parent.kind === SyntaxKind.PrefixOperator) { return true; } - - var parent = node.parent; - if (parent) { - if (parent.kind === SyntaxKind.PostfixOperator || parent.kind === SyntaxKind.PrefixOperator) { - return true; - } - 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 false; + else if (parent.kind === SyntaxKind.BinaryExpression && (parent).left === node) { + var operator = (parent).operator; + return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment; } } + + return false; } /// Syntactic features diff --git a/tests/cases/fourslash/findAllRefsThisKeywordMultipleFiles.ts b/tests/cases/fourslash/findAllRefsThisKeywordMultipleFiles.ts new file mode 100644 index 00000000000..bc31ffd1579 --- /dev/null +++ b/tests/cases/fourslash/findAllRefsThisKeywordMultipleFiles.ts @@ -0,0 +1,15 @@ +/// + +// @Filename: file1.ts +////this; this; + +// @Filename: file2.ts +////this; +////this; + +// @Filename: file3.ts +//// ((x = this, y) => t/**/his)(this, this); + +goTo.file("file1.ts"); +goTo.marker(); +verify.referencesCountIs(8); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesThis.ts b/tests/cases/fourslash/getOccurrencesThis.ts new file mode 100644 index 00000000000..e4b059b9cf9 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesThis.ts @@ -0,0 +1,154 @@ +/// + +////[|this|]; +////[|th/**/is|]; +//// +////function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +////} +//// +////module m { +//// function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////class A { +//// public b = this.method1; +//// +//// public method1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private method2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// public static staticB = this.staticMethod1; +//// +//// public static staticMethod1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private static staticMethod2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////var x = { +//// f() { +//// this; +//// }, +//// g() { +//// this; +//// } +////} + +test.ranges().forEach(r => { + goTo.position(r.start); + + test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); + }); +}); + +goTo.marker(); +test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesThis2.ts b/tests/cases/fourslash/getOccurrencesThis2.ts new file mode 100644 index 00000000000..3df30369e3e --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesThis2.ts @@ -0,0 +1,154 @@ +/// + +////this; +////this; +//// +////function f() { +//// [|this|]; +//// [|this|]; +//// () => [|this|]; +//// () => { +//// if ([|this|]) { +//// [|this|]; +//// } +//// else { +//// [|t/**/his|].this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +////} +//// +////module m { +//// function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////class A { +//// public b = this.method1; +//// +//// public method1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private method2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// public static staticB = this.staticMethod1; +//// +//// public static staticMethod1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private static staticMethod2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////var x = { +//// f() { +//// this; +//// }, +//// g() { +//// this; +//// } +////} + +test.ranges().forEach(r => { + goTo.position(r.start); + + test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); + }); +}); + +goTo.marker(); +test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesThis3.ts b/tests/cases/fourslash/getOccurrencesThis3.ts new file mode 100644 index 00000000000..7ee18a31286 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesThis3.ts @@ -0,0 +1,154 @@ +/// + +////this; +////this; +//// +////function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// [|t/**/his|]; +//// (function (_) { +//// this; +//// })([|this|]); +//// } +////} +//// +////module m { +//// function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////class A { +//// public b = this.method1; +//// +//// public method1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private method2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// public static staticB = this.staticMethod1; +//// +//// public static staticMethod1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private static staticMethod2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////var x = { +//// f() { +//// this; +//// }, +//// g() { +//// this; +//// } +////} + +test.ranges().forEach(r => { + goTo.position(r.start); + + test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); + }); +}); + +goTo.marker(); +test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesThis4.ts b/tests/cases/fourslash/getOccurrencesThis4.ts new file mode 100644 index 00000000000..75a9383f88e --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesThis4.ts @@ -0,0 +1,154 @@ +/// + +////this; +////this; +//// +////function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +////} +//// +////module m { +//// function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////class A { +//// public b = [|this|].method1; +//// +//// public method1() { +//// [|this|]; +//// [|this|]; +//// () => [|this|]; +//// () => { +//// if ([|this|]) { +//// [|this|]; +//// } +//// else { +//// [|this|].this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private method2() { +//// [|this|]; +//// [|this|]; +//// () => [|t/**/his|]; +//// () => { +//// if ([|this|]) { +//// [|this|]; +//// } +//// else { +//// [|this|].this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// public static staticB = this.staticMethod1; +//// +//// public static staticMethod1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private static staticMethod2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////var x = { +//// f() { +//// this; +//// }, +//// g() { +//// this; +//// } +////} + +test.ranges().forEach(r => { + goTo.position(r.start); + + test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); + }); +}); + +goTo.marker(); +test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesThis5.ts b/tests/cases/fourslash/getOccurrencesThis5.ts new file mode 100644 index 00000000000..86ce16b16be --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesThis5.ts @@ -0,0 +1,154 @@ +/// + +////this; +////this; +//// +////function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +////} +//// +////module m { +//// function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////class A { +//// public b = this.method1; +//// +//// public method1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private method2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// public static staticB = [|this|].staticMethod1; +//// +//// public static staticMethod1() { +//// [|this|]; +//// [|this|]; +//// () => [|this|]; +//// () => { +//// if ([|this|]) { +//// [|this|]; +//// } +//// else { +//// [|this|].this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private static staticMethod2() { +//// [|this|]; +//// [|this|]; +//// () => [|this|]; +//// () => { +//// if ([|this|]) { +//// [|this|]; +//// } +//// else { +//// [|t/**/his|].this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////var x = { +//// f() { +//// this; +//// }, +//// g() { +//// this; +//// } +////} + +test.ranges().forEach(r => { + goTo.position(r.start); + + test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); + }); +}); + +goTo.marker(); +test.ranges().forEach(range => { + verify.occurrencesAtPositionContains(range, false); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesThisNegatives.ts b/tests/cases/fourslash/getOccurrencesThisNegatives.ts new file mode 100644 index 00000000000..95c676e0add --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesThisNegatives.ts @@ -0,0 +1,149 @@ +/// + +////this/*1*/; +////this; +//// +////function f() { +//// this/*2*/; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +////} +//// +////module m { +//// var x = th/*6*/is; +//// function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////class A { +//// public b = this.method1; +//// +//// public method1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this/*3*/; +//// })(this); +//// } +//// } +//// +//// private method2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// public static staticB = this.staticMethod1; +//// +//// public static staticMethod1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private static staticMethod2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////var x = { +//// f() { +//// this/*4*/; +//// }, +//// g() { +//// this/*5*/; +//// } +////} + + +test.markers().forEach(m => { + goTo.position(m.position, m.fileName) + + verify.occurrencesAtPositionCount(0); +}); \ No newline at end of file diff --git a/tests/cases/fourslash/getOccurrencesThisNegatives2.ts b/tests/cases/fourslash/getOccurrencesThisNegatives2.ts new file mode 100644 index 00000000000..65fb37d09b4 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesThisNegatives2.ts @@ -0,0 +1,147 @@ +/// + +////this; +////this; +//// +////function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.t/*1*/his; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +////} +//// +////module m { +//// function f() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this./*2*/this; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////class A { +//// public b = this.method1; +//// +//// public method1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.thi/*3*/s; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private method2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.t/*4*/his; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// public static staticB = this.staticMethod1; +//// +//// public static staticMethod1() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.th/*5*/is; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +//// +//// private static staticMethod2() { +//// this; +//// this; +//// () => this; +//// () => { +//// if (this) { +//// this; +//// } +//// else { +//// this.th/*6*/is; +//// } +//// } +//// function inside() { +//// this; +//// (function (_) { +//// this; +//// })(this); +//// } +//// } +////} +//// +////var x = { +//// f() { +//// this; +//// }, +//// g() { +//// this; +//// } +////} + + +test.markers().forEach(m => { + goTo.position(m.position, m.fileName) + verify.occurrencesAtPositionCount(1); +});