@@ -2146,7 +2146,8 @@ module ts {
21462146 return undefined ;
21472147 }
21482148
2149- if ( node . kind === SyntaxKind . Identifier || isLiteralNameOfPropertyDeclarationOrIndexAccess ( node ) || isNameOfExternalModuleImportOrDeclaration ( node ) ) {
2149+ if ( node . kind === SyntaxKind . Identifier || node . kind === SyntaxKind . ThisKeyword ||
2150+ isLiteralNameOfPropertyDeclarationOrIndexAccess ( node ) || isNameOfExternalModuleImportOrDeclaration ( node ) ) {
21502151 return getReferencesForNode ( node , [ sourceFile ] ) ;
21512152 }
21522153
@@ -2243,7 +2244,7 @@ module ts {
22432244 }
22442245
22452246 // Ordinary case: just highlight the keyword.
2246- result . push ( keywordToReferenceEntry ( keywords [ i ] ) ) ;
2247+ result . push ( getReferenceEntryFromNode ( keywords [ i ] ) ) ;
22472248 }
22482249
22492250 return result ;
@@ -2262,7 +2263,7 @@ module ts {
22622263 pushKeywordIf ( keywords , returnStatement . getFirstToken ( ) , SyntaxKind . ReturnKeyword ) ;
22632264 } ) ;
22642265
2265- return map ( keywords , keywordToReferenceEntry ) ;
2266+ return map ( keywords , getReferenceEntryFromNode ) ;
22662267 }
22672268
22682269 function getTryCatchFinallyOccurrences ( tryStatement : TryStatement ) : ReferenceEntry [ ] {
@@ -2278,7 +2279,7 @@ module ts {
22782279 pushKeywordIf ( keywords , tryStatement . finallyBlock . getFirstToken ( ) , SyntaxKind . FinallyKeyword ) ;
22792280 }
22802281
2281- return map ( keywords , keywordToReferenceEntry ) ;
2282+ return map ( keywords , getReferenceEntryFromNode ) ;
22822283 }
22832284
22842285 function getSwitchCaseDefaultOccurrences ( switchStatement : SwitchStatement ) {
@@ -2314,7 +2315,7 @@ module ts {
23142315 } ) ;
23152316 } ) ;
23162317
2317- return map ( keywords , keywordToReferenceEntry ) ;
2318+ return map ( keywords , getReferenceEntryFromNode ) ;
23182319 }
23192320
23202321 function getBreakStatementOccurences ( breakStatement : BreakOrContinueStatement ) : ReferenceEntry [ ] {
@@ -2363,10 +2364,6 @@ module ts {
23632364
23642365 return false ;
23652366 }
2366-
2367- function keywordToReferenceEntry ( keyword : Node ) : ReferenceEntry {
2368- return new ReferenceEntry ( filename , TypeScript . TextSpan . fromBounds ( keyword . getStart ( ) , keyword . end ) , /* isWriteAccess */ false ) ;
2369- }
23702367 }
23712368
23722369 function getReferencesAtPosition ( filename : string , position : number ) : ReferenceEntry [ ] {
@@ -2381,6 +2378,7 @@ module ts {
23812378 }
23822379
23832380 if ( node . kind !== SyntaxKind . Identifier &&
2381+ node . kind !== SyntaxKind . ThisKeyword &&
23842382 ! isLiteralNameOfPropertyDeclarationOrIndexAccess ( node ) &&
23852383 ! isNameOfExternalModuleImportOrDeclaration ( node ) ) {
23862384 return undefined ;
@@ -2396,21 +2394,25 @@ module ts {
23962394 var labelDefinition = getTargetLabel ( ( < BreakOrContinueStatement > node . parent ) , ( < Identifier > node ) . text ) ;
23972395 // if we have a label definition, look within its statement for references, if not, then
23982396 // the label is undefined, just return a set of one for the current node.
2399- return labelDefinition ? getLabelReferencesInNode ( labelDefinition . parent , labelDefinition ) : [ getReferenceEntry ( node ) ] ;
2397+ return labelDefinition ? getLabelReferencesInNode ( labelDefinition . parent , labelDefinition ) : [ getReferenceEntryFromNode ( node ) ] ;
24002398 }
24012399 else {
24022400 // it is a label definition and not a target, search within the parent labeledStatement
24032401 return getLabelReferencesInNode ( node . parent , < Identifier > node ) ;
24042402 }
24052403 }
24062404
2405+ if ( node . kind === SyntaxKind . ThisKeyword ) {
2406+ return getReferencesForThisKeyword ( node , sourceFiles ) ;
2407+ }
2408+
24072409 var symbol = typeInfoResolver . getSymbolInfo ( node ) ;
24082410
24092411 // Could not find a symbol e.g. unknown identifier
24102412 if ( ! symbol ) {
24112413 // Even if we did not find a symbol, we have an identifer, so there is at least
2412- // one reference that we know of. return than instead of undefined.
2413- return [ getReferenceEntry ( node ) ] ;
2414+ // one reference that we know of. return that instead of undefined.
2415+ return [ getReferenceEntryFromNode ( node ) ] ;
24142416 }
24152417
24162418 // the symbol was an internal symbol and does not have a declaration e.g.undefined symbol
@@ -2554,7 +2556,7 @@ module ts {
25542556 // Only pick labels that are either the target label, or have a target that is the target label
25552557 if ( node === targetLabel ||
25562558 ( isJumpStatementTarget ( node ) && getTargetLabel ( node , labelName ) === targetLabel ) ) {
2557- result . push ( getReferenceEntry ( node ) ) ;
2559+ result . push ( getReferenceEntryFromNode ( node ) ) ;
25582560 }
25592561 } ) ;
25602562 return result ;
@@ -2619,7 +2621,96 @@ module ts {
26192621 }
26202622
26212623 if ( isRelatableToSearchSet ( searchSymbols , referenceSymbol , referenceLocation ) ) {
2622- result . push ( getReferenceEntry ( referenceLocation ) ) ;
2624+ result . push ( getReferenceEntryFromNode ( referenceLocation ) ) ;
2625+ }
2626+ } ) ;
2627+ }
2628+ }
2629+
2630+ function getReferencesForThisKeyword ( thisKeyword : Node , sourceFiles : SourceFile [ ] ) {
2631+ // Get the owner" of the 'this' keyword.
2632+ var thisContainer = getThisContainer ( thisKeyword , /* includeArrowFunctions */ false ) ;
2633+
2634+ var searchSpaceNode : Node ;
2635+
2636+ // Whether 'this' occurs in a static context within a class;
2637+ var staticFlag = NodeFlags . Static ;
2638+
2639+ switch ( thisContainer . kind ) {
2640+ case SyntaxKind . Property :
2641+ case SyntaxKind . Method :
2642+ case SyntaxKind . Constructor :
2643+ case SyntaxKind . GetAccessor :
2644+ case SyntaxKind . SetAccessor :
2645+ searchSpaceNode = thisContainer . parent ; // should be the owning class
2646+ staticFlag &= thisContainer . flags
2647+ break ;
2648+ case SyntaxKind . SourceFile :
2649+ if ( isExternalModule ( < SourceFile > thisContainer ) ) {
2650+ return undefined ;
2651+ }
2652+ // Fall through
2653+ case SyntaxKind . FunctionDeclaration :
2654+ case SyntaxKind . FunctionExpression :
2655+ searchSpaceNode = thisContainer ;
2656+ break ;
2657+ default :
2658+ return undefined ;
2659+ }
2660+
2661+ var result : ReferenceEntry [ ] = [ ] ;
2662+
2663+ if ( searchSpaceNode . kind === SyntaxKind . SourceFile ) {
2664+ forEach ( sourceFiles , sourceFile => {
2665+ var possiblePositions = getPossibleSymbolReferencePositions ( sourceFile , "this" , sourceFile . getStart ( ) , sourceFile . getEnd ( ) ) ;
2666+ getThisReferencesInFile ( sourceFile , sourceFile , possiblePositions , result ) ;
2667+ } ) ;
2668+ }
2669+ else {
2670+ var sourceFile = searchSpaceNode . getSourceFile ( ) ;
2671+ var possiblePositions = getPossibleSymbolReferencePositions ( sourceFile , "this" , searchSpaceNode . getStart ( ) , searchSpaceNode . getEnd ( ) ) ;
2672+ getThisReferencesInFile ( sourceFile , searchSpaceNode , possiblePositions , result ) ;
2673+ }
2674+
2675+ return result ;
2676+
2677+ function getThisReferencesInFile ( sourceFile : SourceFile , searchSpaceNode : Node , possiblePositions : number [ ] , result : ReferenceEntry [ ] ) : void {
2678+ forEach ( possiblePositions , position => {
2679+ cancellationToken . throwIfCancellationRequested ( ) ;
2680+
2681+ var node = getNodeAtPosition ( sourceFile , position ) ;
2682+ if ( ! node || node . kind !== SyntaxKind . ThisKeyword ) {
2683+ return ;
2684+ }
2685+
2686+ // Get the owner of the 'this' keyword.
2687+ // This *should* be a node that occurs somewhere within searchSpaceNode.
2688+ var container = getThisContainer ( node , /* includeArrowFunctions */ false ) ;
2689+
2690+ switch ( container . kind ) {
2691+ case SyntaxKind . Property :
2692+ case SyntaxKind . Method :
2693+ case SyntaxKind . Constructor :
2694+ case SyntaxKind . GetAccessor :
2695+ case SyntaxKind . SetAccessor :
2696+ // Make sure the container belongs to the same class
2697+ // and has the appropriate static modifier from the original container.
2698+ if ( searchSpaceNode . symbol === container . parent . symbol && ( container . flags & NodeFlags . Static ) === staticFlag ) {
2699+ result . push ( getReferenceEntryFromNode ( node ) ) ;
2700+ }
2701+ break ;
2702+ case SyntaxKind . FunctionDeclaration :
2703+ case SyntaxKind . FunctionExpression :
2704+ if ( searchSpaceNode . symbol === container . symbol ) {
2705+ result . push ( getReferenceEntryFromNode ( node ) ) ;
2706+ }
2707+ break ;
2708+ case SyntaxKind . SourceFile :
2709+ // Add all 'this' keywords that belong to the top-level scope.
2710+ if ( searchSpaceNode . kind === SyntaxKind . SourceFile && ! isExternalModule ( < SourceFile > searchSpaceNode ) ) {
2711+ result . push ( getReferenceEntryFromNode ( node ) ) ;
2712+ }
2713+ break ;
26232714 }
26242715 } ) ;
26252716 }
@@ -2721,18 +2812,6 @@ module ts {
27212812 return undefined ;
27222813 }
27232814
2724- function getReferenceEntry ( node : Node ) : ReferenceEntry {
2725- var start = node . getStart ( ) ;
2726- var end = node . getEnd ( ) ;
2727-
2728- if ( node . kind === SyntaxKind . StringLiteral ) {
2729- start += 1 ;
2730- end -= 1 ;
2731- }
2732-
2733- return new ReferenceEntry ( node . getSourceFile ( ) . filename , TypeScript . TextSpan . fromBounds ( start , end ) , isWriteAccess ( node ) ) ;
2734- }
2735-
27362815 function getMeaningFromDeclaration ( node : Declaration ) : SearchMeaning {
27372816 switch ( node . kind ) {
27382817 case SyntaxKind . Parameter :
@@ -2869,40 +2948,38 @@ module ts {
28692948 }
28702949 return meaning ;
28712950 }
2951+ }
28722952
2873- /// A node is considedered a writeAccess iff it is a name of a declaration or a target of an assignment
2874- function isWriteAccess ( node : Node ) : boolean {
2875- if ( node . kind === SyntaxKind . Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName ( node ) ) {
2876- return true ;
2877- }
2953+ function getReferenceEntryFromNode ( node : Node ) : ReferenceEntry {
2954+ var start = node . getStart ( ) ;
2955+ var end = node . getEnd ( ) ;
28782956
2879- var parent = node . parent ;
2880- if ( parent ) {
2881- if ( parent . kind === SyntaxKind . PostfixOperator || parent . kind === SyntaxKind . PrefixOperator ) {
2882- return true ;
2883- }
2884- else if ( parent . kind === SyntaxKind . BinaryExpression && ( < BinaryExpression > parent ) . left === node ) {
2885- var operator = ( < BinaryExpression > parent ) . operator ;
2886- switch ( operator ) {
2887- case SyntaxKind . AsteriskEqualsToken :
2888- case SyntaxKind . SlashEqualsToken :
2889- case SyntaxKind . PercentEqualsToken :
2890- case SyntaxKind . MinusEqualsToken :
2891- case SyntaxKind . LessThanLessThanEqualsToken :
2892- case SyntaxKind . GreaterThanGreaterThanEqualsToken :
2893- case SyntaxKind . GreaterThanGreaterThanGreaterThanEqualsToken :
2894- case SyntaxKind . BarEqualsToken :
2895- case SyntaxKind . CaretEqualsToken :
2896- case SyntaxKind . AmpersandEqualsToken :
2897- case SyntaxKind . PlusEqualsToken :
2898- case SyntaxKind . EqualsToken :
2899- return true ;
2900- }
2901- }
2957+ if ( node . kind === SyntaxKind . StringLiteral ) {
2958+ start += 1 ;
2959+ end -= 1 ;
2960+ }
29022961
2903- return false ;
2962+ return new ReferenceEntry ( node . getSourceFile ( ) . filename , TypeScript . TextSpan . fromBounds ( start , end ) , isWriteAccess ( node ) ) ;
2963+ }
2964+
2965+ /// A node is considedered a writeAccess iff it is a name of a declaration or a target of an assignment
2966+ function isWriteAccess ( node : Node ) : boolean {
2967+ if ( node . kind === SyntaxKind . Identifier && isDeclarationOrFunctionExpressionOrCatchVariableName ( node ) ) {
2968+ return true ;
2969+ }
2970+
2971+ var parent = node . parent ;
2972+ if ( parent ) {
2973+ if ( parent . kind === SyntaxKind . PostfixOperator || parent . kind === SyntaxKind . PrefixOperator ) {
2974+ return true ;
2975+ }
2976+ else if ( parent . kind === SyntaxKind . BinaryExpression && ( < BinaryExpression > parent ) . left === node ) {
2977+ var operator = ( < BinaryExpression > parent ) . operator ;
2978+ return SyntaxKind . FirstAssignment <= operator && operator <= SyntaxKind . LastAssignment ;
29042979 }
29052980 }
2981+
2982+ return false ;
29062983 }
29072984
29082985 /// Syntactic features
0 commit comments