Merge pull request #653 from Microsoft/getOccurrences

getOccurrencesAtPosition Implemented
This commit is contained in:
Daniel Rosenwasser 2014-09-11 12:02:06 -07:00
commit 86691f0883
28 changed files with 2051 additions and 146 deletions

View file

@ -3468,29 +3468,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;
@ -3503,11 +3480,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;
}
@ -4407,37 +4387,6 @@ module ts {
return voidType;
}
// WARNING: This has the same semantics as the forEach family of functions,
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
return traverse(body);
function traverse(node: Node): T {
switch (node.kind) {
case SyntaxKind.ReturnStatement:
return visitor(node);
case SyntaxKind.Block:
case SyntaxKind.FunctionBlock:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabelledStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
return forEachChild(node, traverse);
}
}
}
/// Returns a set of types relating to every return expression relating to a function block.
function checkAndAggregateReturnExpressionTypes(body: Block, contextualMapper?: TypeMapper): Type[] {
var aggregatedTypes: Type[] = [];
@ -5856,17 +5805,6 @@ module ts {
// TODO: Check that target label is valid
}
function getContainingFunction(node: Node): SignatureDeclaration {
while (true) {
node = node.parent;
if (!node || node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression ||
node.kind === SyntaxKind.ArrowFunction || node.kind === SyntaxKind.Method || node.kind === SyntaxKind.Constructor ||
node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
return <SignatureDeclaration>node;
}
}
}
function checkReturnStatement(node: ReturnStatement) {
if (node.expression && !(getNodeLinks(node.expression).flags & NodeCheckFlags.TypeChecked)) {
var func = getContainingFunction(node);

View file

@ -350,6 +350,107 @@ module ts {
}
}
// Warning: This has the same semantics as the forEach family of functions,
// in that traversal terminates in the event that 'visitor' supplies a truthy value.
export function forEachReturnStatement<T>(body: Block, visitor: (stmt: ReturnStatement) => T): T {
return traverse(body);
function traverse(node: Node): T {
switch (node.kind) {
case SyntaxKind.ReturnStatement:
return visitor(node);
case SyntaxKind.Block:
case SyntaxKind.FunctionBlock:
case SyntaxKind.IfStatement:
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.WithStatement:
case SyntaxKind.SwitchStatement:
case SyntaxKind.CaseClause:
case SyntaxKind.DefaultClause:
case SyntaxKind.LabelledStatement:
case SyntaxKind.TryStatement:
case SyntaxKind.TryBlock:
case SyntaxKind.CatchBlock:
case SyntaxKind.FinallyBlock:
return forEachChild(node, traverse);
}
}
}
export function isAnyFunction(node: Node): boolean {
if (node) {
switch (node.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Method:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.Constructor:
return true;
}
}
return false;
}
export function getContainingFunction(node: Node): SignatureDeclaration {
while (true) {
node = node.parent;
if (!node || isAnyFunction(node)) {
return <SignatureDeclaration>node;
}
}
}
export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
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 getSuperContainer(node: Node): Node {
while (true) {
node = node.parent;
if (!node) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.Property:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return node;
}
}
}
export function hasRestParameters(s: SignatureDeclaration): boolean {
return s.parameters.length > 0 && (s.parameters[s.parameters.length - 1].flags & NodeFlags.Rest) !== 0;
}

View file

@ -220,7 +220,7 @@ module ts {
LastFutureReservedWord = YieldKeyword,
FirstTypeNode = TypeReference,
LastTypeNode = ArrayType,
FirstPunctuation= OpenBraceToken,
FirstPunctuation = OpenBraceToken,
LastPunctuation = CaretEqualsToken
}

View file

@ -1312,20 +1312,6 @@ module ts {
return node.parent.kind === SyntaxKind.NewExpression && (<CallExpression>node.parent).func === node;
}
function isAnyFunction(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.ArrowFunction:
case SyntaxKind.Method:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.Constructor:
return true;
}
return false;
}
function isNameOfFunctionDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.Identifier &&
isAnyFunction(node.parent) && (<FunctionDeclaration>node.parent).name === node;
@ -2148,7 +2134,6 @@ module ts {
return result;
}
/// Find references
function getOccurrencesAtPosition(filename: string, position: number): ReferenceEntry[] {
synchronizeHostData();
@ -2160,11 +2145,23 @@ module ts {
return undefined;
}
if (node.kind === SyntaxKind.Identifier || isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) {
if (node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.ThisKeyword || node.kind === SyntaxKind.SuperKeyword ||
isLiteralNameOfPropertyDeclarationOrIndexAccess(node) || isNameOfExternalModuleImportOrDeclaration(node)) {
return getReferencesForNode(node, [sourceFile]);
}
switch (node.kind) {
case SyntaxKind.IfKeyword:
case SyntaxKind.ElseKeyword:
if (hasKind(node.parent, SyntaxKind.IfStatement)) {
return getIfElseOccurrences(<IfStatement>node.parent);
}
break;
case SyntaxKind.ReturnKeyword:
if (hasKind(node.parent, SyntaxKind.ReturnStatement)) {
return getReturnOccurrences(<ReturnStatement>node.parent);
}
break;
case SyntaxKind.TryKeyword:
case SyntaxKind.CatchKeyword:
case SyntaxKind.FinallyKeyword:
@ -2188,10 +2185,91 @@ module ts {
return getBreakStatementOccurences(<BreakOrContinueStatement>node.parent);
}
break;
case SyntaxKind.ConstructorKeyword:
if (hasKind(node.parent, SyntaxKind.Constructor)) {
return getConstructorOccurrences(<ConstructorDeclaration>node.parent);
}
break;
}
return undefined;
function getIfElseOccurrences(ifStatement: IfStatement): ReferenceEntry[] {
var keywords: Node[] = [];
// Traverse upwards through all parent if-statements linked by their else-branches.
while (hasKind(ifStatement.parent, SyntaxKind.IfStatement) && (<IfStatement>ifStatement.parent).elseStatement === ifStatement) {
ifStatement = <IfStatement>ifStatement.parent;
}
// Now traverse back down through the else branches, aggregating if/else keywords of if-statements.
while (ifStatement) {
var children = ifStatement.getChildren();
pushKeywordIf(keywords, children[0], SyntaxKind.IfKeyword);
// Generally the 'else' keyword is second-to-last, so we traverse backwards.
for (var i = children.length - 1; i >= 0; i--) {
if (pushKeywordIf(keywords, children[i], SyntaxKind.ElseKeyword)) {
break;
}
}
if (!hasKind(ifStatement.elseStatement, SyntaxKind.IfStatement)) {
break
}
ifStatement = <IfStatement>ifStatement.elseStatement;
}
var result: ReferenceEntry[] = [];
// We'd like to highlight else/ifs together if they are only separated by whitespace
// (i.e. the keywords are separated by no comments, no newlines).
for (var i = 0; i < keywords.length; i++) {
if (keywords[i].kind === SyntaxKind.ElseKeyword && i < keywords.length - 1) {
var elseKeyword = keywords[i];
var ifKeyword = keywords[i + 1]; // this *should* always be an 'if' keyword.
var shouldHighlightNextKeyword = true;
// Avoid recalculating getStart() by iterating backwards.
for (var j = ifKeyword.getStart() - 1; j >= elseKeyword.end; j--) {
if (!isWhiteSpace(sourceFile.text.charCodeAt(j))) {
shouldHighlightNextKeyword = false;
break;
}
}
if (shouldHighlightNextKeyword) {
result.push(new ReferenceEntry(filename, TypeScript.TextSpan.fromBounds(elseKeyword.getStart(), ifKeyword.end), /* isWriteAccess */ false));
i++; // skip the next keyword
continue;
}
}
// Ordinary case: just highlight the keyword.
result.push(getReferenceEntryFromNode(keywords[i]));
}
return result;
}
function getReturnOccurrences(returnStatement: ReturnStatement): ReferenceEntry[] {
var func = <FunctionDeclaration>getContainingFunction(returnStatement);
// If we didn't find a containing function with a block body, bail out.
if (!(func && hasKind(func.body, SyntaxKind.FunctionBlock))) {
return undefined;
}
var keywords: Node[] = []
forEachReturnStatement(<Block>(<FunctionDeclaration>func).body, returnStatement => {
pushKeywordIf(keywords, returnStatement.getFirstToken(), SyntaxKind.ReturnKeyword);
});
return map(keywords, getReferenceEntryFromNode);
}
function getTryCatchFinallyOccurrences(tryStatement: TryStatement): ReferenceEntry[] {
var keywords: Node[] = [];
@ -2205,7 +2283,7 @@ module ts {
pushKeywordIf(keywords, tryStatement.finallyBlock.getFirstToken(), SyntaxKind.FinallyKeyword);
}
return keywordsToReferenceEntries(keywords);
return map(keywords, getReferenceEntryFromNode);
}
function getSwitchCaseDefaultOccurrences(switchStatement: SwitchStatement) {
@ -2241,10 +2319,10 @@ module ts {
});
});
return keywordsToReferenceEntries(keywords);
return map(keywords, getReferenceEntryFromNode);
}
function getBreakStatementOccurences(breakStatement: BreakOrContinueStatement): ReferenceEntry[]{
function getBreakStatementOccurences(breakStatement: BreakOrContinueStatement): ReferenceEntry[] {
// TODO (drosen): Deal with labeled statements.
if (breakStatement.label) {
return undefined;
@ -2272,6 +2350,20 @@ module ts {
return undefined;
}
function getConstructorOccurrences(constructorDeclaration: ConstructorDeclaration): ReferenceEntry[] {
var declarations = constructorDeclaration.symbol.getDeclarations()
var keywords: Node[] = [];
forEach(declarations, declaration => {
forEach(declaration.getChildren(), token => {
return pushKeywordIf(keywords, token, SyntaxKind.ConstructorKeyword);
});
});
return map(keywords, getReferenceEntryFromNode);
}
// returns true if 'node' is defined and has a matching 'kind'.
function hasKind(node: Node, kind: SyntaxKind) {
return !!(node && node.kind === kind);
@ -2282,20 +2374,13 @@ module ts {
return node && node.parent;
}
function pushKeywordIf(keywordList: Node[], token: Node, ...expected: SyntaxKind[]): void {
if (!token) {
return;
}
if (contains(<SyntaxKind[]>expected, token.kind)) {
function pushKeywordIf(keywordList: Node[], token: Node, ...expected: SyntaxKind[]): boolean {
if (token && contains(expected, token.kind)) {
keywordList.push(token);
return true;
}
}
function keywordsToReferenceEntries(keywords: Node[]): ReferenceEntry[]{
return map(keywords, keyword =>
new ReferenceEntry(filename, TypeScript.TextSpan.fromBounds(keyword.getStart(), keyword.end), /* isWriteAccess */ false)
);
return false;
}
}
@ -2311,6 +2396,9 @@ module ts {
}
if (node.kind !== SyntaxKind.Identifier &&
// TODO (drosen): This should be enabled in a later release - currently breaks rename.
//node.kind !== SyntaxKind.ThisKeyword &&
//node.kind !== SyntaxKind.SuperKeyword &&
!isLiteralNameOfPropertyDeclarationOrIndexAccess(node) &&
!isNameOfExternalModuleImportOrDeclaration(node)) {
return undefined;
@ -2326,7 +2414,7 @@ module ts {
var labelDefinition = getTargetLabel((<BreakOrContinueStatement>node.parent), (<Identifier>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
@ -2334,13 +2422,21 @@ module ts {
}
}
if (node.kind === SyntaxKind.ThisKeyword) {
return getReferencesForThisKeyword(node, sourceFiles);
}
if (node.kind === SyntaxKind.SuperKeyword) {
return getReferencesForSuperKeyword(node);
}
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
@ -2484,7 +2580,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;
@ -2549,7 +2645,132 @@ module ts {
}
if (isRelatableToSearchSet(searchSymbols, referenceSymbol, referenceLocation)) {
result.push(getReferenceEntry(referenceLocation));
result.push(getReferenceEntryFromNode(referenceLocation));
}
});
}
}
function getReferencesForSuperKeyword(superKeyword: Node): ReferenceEntry[]{
var searchSpaceNode = getSuperContainer(superKeyword);
if (!searchSpaceNode) {
return undefined;
}
// Whether 'super' occurs in a static context within a class.
var staticFlag = NodeFlags.Static;
switch (searchSpaceNode.kind) {
case SyntaxKind.Property:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
staticFlag &= searchSpaceNode.flags;
searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
break;
default:
return undefined;
}
var result: ReferenceEntry[] = [];
var sourceFile = searchSpaceNode.getSourceFile();
var possiblePositions = getPossibleSymbolReferencePositions(sourceFile, "super", searchSpaceNode.getStart(), searchSpaceNode.getEnd());
forEach(possiblePositions, position => {
cancellationToken.throwIfCancellationRequested();
var node = getNodeAtPosition(sourceFile, position);
if (!node || node.kind !== SyntaxKind.SuperKeyword) {
return;
}
var container = getSuperContainer(node);
// If we have a 'super' container, we must have an enclosing class.
// Now make sure the owning class is the same as the search-space
// and has the same static qualifier as the original 'super's owner.
if (container && (NodeFlags.Static & container.flags) === staticFlag && container.parent.symbol === searchSpaceNode.symbol) {
result.push(getReferenceEntryFromNode(node));
}
});
return result;
}
function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: SourceFile[]): ReferenceEntry[] {
var searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false);
// Whether 'this' occurs in a static context within a class.
var staticFlag = NodeFlags.Static;
switch (searchSpaceNode.kind) {
case SyntaxKind.Property:
case SyntaxKind.Method:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
staticFlag &= searchSpaceNode.flags
searchSpaceNode = searchSpaceNode.parent; // re-assign to be the owning class
break;
case SyntaxKind.SourceFile:
if (isExternalModule(<SourceFile>searchSpaceNode)) {
return undefined;
}
// Fall through
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
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;
}
var container = getThisContainer(node, /* includeArrowFunctions */ false);
switch (searchSpaceNode.kind) {
case SyntaxKind.FunctionExpression:
case SyntaxKind.FunctionDeclaration:
if (searchSpaceNode.symbol === container.symbol) {
result.push(getReferenceEntryFromNode(node));
}
break;
case SyntaxKind.ClassDeclaration:
// Make sure the container belongs to the same class
// and has the appropriate static modifier from the original container.
if (container.parent && searchSpaceNode.symbol === container.parent.symbol && (container.flags & NodeFlags.Static) === staticFlag) {
result.push(getReferenceEntryFromNode(node));
}
break;
case SyntaxKind.SourceFile:
if (container.kind === SyntaxKind.SourceFile && !isExternalModule(<SourceFile>container)) {
result.push(getReferenceEntryFromNode(node));
}
break;
}
});
}
@ -2651,18 +2872,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:
@ -2799,40 +3008,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 && (<BinaryExpression>parent).left === node) {
var operator = (<BinaryExpression>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 && (<BinaryExpression>parent).left === node) {
var operator = (<BinaryExpression>parent).operator;
return SyntaxKind.FirstAssignment <= operator && operator <= SyntaxKind.LastAssignment;
}
}
return false;
}
/// Syntactic features

View file

@ -0,0 +1,18 @@
/// <reference path='fourslash.ts' />
// @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();
// TODO (drosen): The CURRENT behavior is that findAllRefs doesn't work on 'this' or 'super' keywords.
// This should change down the line.
verify.referencesCountIs(0);

View file

@ -0,0 +1,32 @@
/// <reference path='fourslash.ts' />
////class C {
//// [|const/**/ructor|]();
//// [|constructor|](x: number);
//// [|constructor|](y: string, x: number);
//// [|constructor|](a?: any, ...r: any[]) {
//// if (a === undefined && r.length === 0) {
//// return;
//// }
////
//// return;
//// }
////}
////
////class D {
//// constructor(public x: number, public y: number) {
//// }
////}
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);
});

View file

@ -0,0 +1,32 @@
/// <reference path='fourslash.ts' />
////class C {
//// constructor();
//// constructor(x: number);
//// constructor(y: string, x: number);
//// constructor(a?: any, ...r: any[]) {
//// if (a === undefined && r.length === 0) {
//// return;
//// }
////
//// return;
//// }
////}
////
////class D {
//// [|con/**/structor|](public x: number, public y: number) {
//// }
////}
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);
});

View file

@ -0,0 +1,36 @@
/// <reference path='fourslash.ts' />
////[|if|] (true) {
//// if (false) {
//// }
//// else {
//// }
//// if (true) {
//// }
//// else {
//// if (false)
//// if (true)
//// var x = undefined;
//// }
////}
////[|else i/**/f|] (null) {
////}
////[|else|] /* whar garbl */ [|if|] (undefined) {
////}
////[|else|]
////[|if|] (false) {
////}
////[|else|] { }
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);
});

View file

@ -0,0 +1,32 @@
/// <reference path='fourslash.ts' />
////if (true) {
//// [|if|] (false) {
//// }
//// [|else|]{
//// }
//// if (true) {
//// }
//// else {
//// if (false)
//// if (true)
//// var x = undefined;
//// }
////}
////else if (null) {
////}
////else /* whar garbl */ if (undefined) {
////}
////else
////if (false) {
////}
////else { }
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});

View file

@ -0,0 +1,32 @@
/// <reference path='fourslash.ts' />
////if (true) {
//// if (false) {
//// }
//// else {
//// }
//// [|if|] (true) {
//// }
//// [|else|] {
//// if (false)
//// if (true)
//// var x = undefined;
//// }
////}
////else if (null) {
////}
////else /* whar garbl */ if (undefined) {
////}
////else
////if (false) {
////}
////else { }
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});

View file

@ -0,0 +1,30 @@
/// <reference path='fourslash.ts' />
////if (true) {
//// if (false) {
//// }
//// else {
//// }
//// if (true) {
//// }
//// else {
//// /*1*/if (false)
//// /*2*/i/*3*/f (true)
//// var x = undefined;
//// }
////}
////else if (null) {
////}
////else /* whar garbl */ if (undefined) {
////}
////else
////if (false) {
////}
////else { }
for (var i = 1; i <= test.markers().length; i++) {
goTo.marker("" + i);
verify.occurrencesAtPositionCount(1);
}

View file

@ -0,0 +1,24 @@
/// <reference path='fourslash.ts' />
////[|if|] (true) {
//// var x = 1;
////}
////[|else if|] ()
////[|else if|]
////[|else|] /* whar garbl */ [|if|] (i/**/f (true) { } else { })
////else
// It would be nice if in the future,
// We could include that last 'else'.
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});
goTo.marker();
verify.occurrencesAtPositionCount(2);

View file

@ -0,0 +1,29 @@
/// <reference path='fourslash.ts' />
////if/*1*/ (true) {
//// if/*2*/ (false) {
//// }
//// else/*3*/ {
//// }
//// if/*4*/ (true) {
//// }
//// else/*5*/ {
//// if/*6*/ (false)
//// if/*7*/ (true)
//// var x = undefined;
//// }
////}
////else/*8*/ if (null) {
////}
////else/*9*/ /* whar garbl */ if/*10*/ (undefined) {
////}
////else/*11*/
////if/*12*/ (false) {
////}
////else/*13*/ { }
test.markers().forEach(m => {
goTo.position(m.position, m.fileName)
verify.occurrencesAtPositionCount(0);
});

View file

@ -0,0 +1,33 @@
/// <reference path='fourslash.ts' />
////function f(a: number) {
//// if (a > 0) {
//// [|ret/**/urn|] (function () {
//// return;
//// return;
//// return;
////
//// if (false) {
//// return true;
//// }
//// })() || true;
//// }
////
//// var unusued = [1, 2, 3, 4].map(x => { return 4 })
////
//// [|return|];
//// [|return|] true;
////}
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);
});

View file

@ -0,0 +1,33 @@
/// <reference path='fourslash.ts' />
////function f(a: number) {
//// if (a > 0) {
//// return (function () {
//// [|return|];
//// [|ret/**/urn|];
//// [|return|];
////
//// while (false) {
//// [|return|] true;
//// }
//// })() || true;
//// }
////
//// var unusued = [1, 2, 3, 4].map(x => { return 4 })
////
//// return;
//// return true;
////}
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);
});

View file

@ -0,0 +1,28 @@
/// <reference path='fourslash.ts' />
////function f(a: number) {
//// if (a > 0) {
//// return (function () {
//// return;
//// return;
//// return;
////
//// if (false) {
//// return true;
//// }
//// })() || true;
//// }
////
//// var unusued = [1, 2, 3, 4].map(x => { [|return|] 4 })
////
//// return;
//// return true;
////}
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});

View file

@ -0,0 +1,54 @@
/// <reference path='fourslash.ts' />
////ret/*1*/urn;
////retu/*2*/rn;
////function f(a: number) {
//// if (a > 0) {
//// return (function () {
//// () => [|return|];
//// [|return|];
//// [|return|];
////
//// if (false) {
//// [|return|] true;
//// }
//// })() || true;
//// }
////
//// var unusued = [1, 2, 3, 4].map(x => { return 4 })
////
//// return;
//// return true;
////}
////
////class A {
//// ret/*3*/urn;
//// r/*4*/eturn 8675309;
////}
// Note: For this test, these 'return's get highlighted as a result of a parse recovery
// where if an arrow function starts with a statement, we try to parse a body
// as if it was missing curly braces. If the behavior changes in the future,
// a change to this test is very much welcome.
test.ranges().forEach(r => {
goTo.position(r.start);
test.ranges().forEach(range => {
verify.occurrencesAtPositionContains(range, false);
});
});
for (var i = 1; i <= test.markers().length; i++) {
goTo.marker("" + i);
switch (i) {
case 0:
case 1:
case 4:
verify.occurrencesAtPositionCount(0);
break;
case 3:
verify.occurrencesAtPositionCount(1); // 'return' is an instance member
break;
}
});

View file

@ -0,0 +1,25 @@
/// <reference path='fourslash.ts' />
////function f(a: number) {
//// if (a > 0) {
//// return (function () {
//// return/*1*/;
//// return/*2*/;
//// return/*3*/;
////
//// if (false) {
//// return/*4*/ true;
//// }
//// })() || true;
//// }
////
//// var unusued = [1, 2, 3, 4].map(x => { return/*5*/ 4 })
////
//// return/*6*/;
//// return/*7*/ true;
////}
test.markers().forEach(m => {
goTo.position(m.position, m.fileName)
verify.occurrencesAtPositionCount(0);
});

View file

@ -0,0 +1,64 @@
/// <reference path='fourslash.ts' />
////class SuperType {
//// superMethod() {
//// }
////
//// static superStaticMethod() {
//// return 10;
//// }
////}
////
////class SubType extends SuperType {
//// public prop1 = [|s/**/uper|].superMethod;
//// private prop2 = [|super|].superMethod;
////
//// constructor() {
//// [|super|]();
//// }
////
//// public method1() {
//// return [|super|].superMethod();
//// }
////
//// private method2() {
//// return [|super|].superMethod();
//// }
////
//// public method3() {
//// var x = () => [|super|].superMethod();
////
//// // Bad but still gets highlighted
//// function f() {
//// [|super|].superMethod();
//// }
//// }
////
//// // Bad but still gets highlighted.
//// public static statProp1 = super.superStaticMethod;
////
//// public static staticMethod1() {
//// return super.superStaticMethod();
//// }
////
//// private static staticMethod2() {
//// return super.superStaticMethod();
//// }
////
//// // Are not actually 'super' keywords.
//// super = 10;
//// static super = 20;
////}
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);
});

View file

@ -0,0 +1,64 @@
/// <reference path='fourslash.ts' />
////class SuperType {
//// superMethod() {
//// }
////
//// static superStaticMethod() {
//// return 10;
//// }
////}
////
////class SubType extends SuperType {
//// public prop1 = super.superMethod;
//// private prop2 = super.superMethod;
////
//// constructor() {
//// super();
//// }
////
//// public method1() {
//// return super.superMethod();
//// }
////
//// private method2() {
//// return super.superMethod();
//// }
////
//// public method3() {
//// var x = () => super.superMethod();
////
//// // Bad but still gets highlighted
//// function f() {
//// super.superMethod();
//// }
//// }
////
//// // Bad but still gets highlighted.
//// public static statProp1 = [|super|].superStaticMethod;
////
//// public static staticMethod1() {
//// return [|super|].superStaticMethod();
//// }
////
//// private static staticMethod2() {
//// return [|supe/**/r|].superStaticMethod();
//// }
////
//// // Are not actually 'super' keywords.
//// super = 10;
//// static super = 20;
////}
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);
});

View file

@ -0,0 +1,27 @@
/// <reference path='fourslash.ts' />
////function f(x = [|super|]) {
//// [|super|];
////}
////
////module M {
//// [|super|];
//// function f(x = [|super|]) {
//// [|super|];
//// }
////
//// class A {
//// }
////
//// class B extends A {
//// constructor() {
//// super();
//// }
//// }
////}
test.ranges().forEach(r => {
goTo.position(r.start);
verify.occurrencesAtPositionCount(0);
});

View file

@ -0,0 +1,154 @@
/// <reference path='fourslash.ts' />
////[|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);
});

View file

@ -0,0 +1,154 @@
/// <reference path='fourslash.ts' />
////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);
});

View file

@ -0,0 +1,154 @@
/// <reference path='fourslash.ts' />
////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);
});

View file

@ -0,0 +1,154 @@
/// <reference path='fourslash.ts' />
////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);
});

View file

@ -0,0 +1,154 @@
/// <reference path='fourslash.ts' />
////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);
});

View file

@ -0,0 +1,149 @@
/// <reference path='fourslash.ts' />
////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);
});

View file

@ -0,0 +1,147 @@
/// <reference path='fourslash.ts' />
////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);
});