@@ -2146,7 +2146,8 @@ module ts {
2146
2146
return undefined ;
2147
2147
}
2148
2148
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 ) ) {
2150
2151
return getReferencesForNode ( node , [ sourceFile ] ) ;
2151
2152
}
2152
2153
@@ -2243,7 +2244,7 @@ module ts {
2243
2244
}
2244
2245
2245
2246
// Ordinary case: just highlight the keyword.
2246
- result . push ( keywordToReferenceEntry ( keywords [ i ] ) ) ;
2247
+ result . push ( getReferenceEntryFromNode ( keywords [ i ] ) ) ;
2247
2248
}
2248
2249
2249
2250
return result ;
@@ -2262,7 +2263,7 @@ module ts {
2262
2263
pushKeywordIf ( keywords , returnStatement . getFirstToken ( ) , SyntaxKind . ReturnKeyword ) ;
2263
2264
} ) ;
2264
2265
2265
- return map ( keywords , keywordToReferenceEntry ) ;
2266
+ return map ( keywords , getReferenceEntryFromNode ) ;
2266
2267
}
2267
2268
2268
2269
function getTryCatchFinallyOccurrences ( tryStatement : TryStatement ) : ReferenceEntry [ ] {
@@ -2278,7 +2279,7 @@ module ts {
2278
2279
pushKeywordIf ( keywords , tryStatement . finallyBlock . getFirstToken ( ) , SyntaxKind . FinallyKeyword ) ;
2279
2280
}
2280
2281
2281
- return map ( keywords , keywordToReferenceEntry ) ;
2282
+ return map ( keywords , getReferenceEntryFromNode ) ;
2282
2283
}
2283
2284
2284
2285
function getSwitchCaseDefaultOccurrences ( switchStatement : SwitchStatement ) {
@@ -2314,7 +2315,7 @@ module ts {
2314
2315
} ) ;
2315
2316
} ) ;
2316
2317
2317
- return map ( keywords , keywordToReferenceEntry ) ;
2318
+ return map ( keywords , getReferenceEntryFromNode ) ;
2318
2319
}
2319
2320
2320
2321
function getBreakStatementOccurences ( breakStatement : BreakOrContinueStatement ) : ReferenceEntry [ ] {
@@ -2363,10 +2364,6 @@ module ts {
2363
2364
2364
2365
return false ;
2365
2366
}
2366
-
2367
- function keywordToReferenceEntry ( keyword : Node ) : ReferenceEntry {
2368
- return new ReferenceEntry ( filename , TypeScript . TextSpan . fromBounds ( keyword . getStart ( ) , keyword . end ) , /* isWriteAccess */ false ) ;
2369
- }
2370
2367
}
2371
2368
2372
2369
function getReferencesAtPosition ( filename : string , position : number ) : ReferenceEntry [ ] {
@@ -2381,6 +2378,7 @@ module ts {
2381
2378
}
2382
2379
2383
2380
if ( node . kind !== SyntaxKind . Identifier &&
2381
+ node . kind !== SyntaxKind . ThisKeyword &&
2384
2382
! isLiteralNameOfPropertyDeclarationOrIndexAccess ( node ) &&
2385
2383
! isNameOfExternalModuleImportOrDeclaration ( node ) ) {
2386
2384
return undefined ;
@@ -2396,21 +2394,25 @@ module ts {
2396
2394
var labelDefinition = getTargetLabel ( ( < BreakOrContinueStatement > node . parent ) , ( < Identifier > node ) . text ) ;
2397
2395
// if we have a label definition, look within its statement for references, if not, then
2398
2396
// 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 ) ] ;
2400
2398
}
2401
2399
else {
2402
2400
// it is a label definition and not a target, search within the parent labeledStatement
2403
2401
return getLabelReferencesInNode ( node . parent , < Identifier > node ) ;
2404
2402
}
2405
2403
}
2406
2404
2405
+ if ( node . kind === SyntaxKind . ThisKeyword ) {
2406
+ return getReferencesForThisKeyword ( node , sourceFiles ) ;
2407
+ }
2408
+
2407
2409
var symbol = typeInfoResolver . getSymbolInfo ( node ) ;
2408
2410
2409
2411
// Could not find a symbol e.g. unknown identifier
2410
2412
if ( ! symbol ) {
2411
2413
// 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 ) ] ;
2414
2416
}
2415
2417
2416
2418
// the symbol was an internal symbol and does not have a declaration e.g.undefined symbol
@@ -2554,7 +2556,7 @@ module ts {
2554
2556
// Only pick labels that are either the target label, or have a target that is the target label
2555
2557
if ( node === targetLabel ||
2556
2558
( isJumpStatementTarget ( node ) && getTargetLabel ( node , labelName ) === targetLabel ) ) {
2557
- result . push ( getReferenceEntry ( node ) ) ;
2559
+ result . push ( getReferenceEntryFromNode ( node ) ) ;
2558
2560
}
2559
2561
} ) ;
2560
2562
return result ;
@@ -2619,7 +2621,96 @@ module ts {
2619
2621
}
2620
2622
2621
2623
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 ;
2623
2714
}
2624
2715
} ) ;
2625
2716
}
@@ -2721,18 +2812,6 @@ module ts {
2721
2812
return undefined ;
2722
2813
}
2723
2814
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
-
2736
2815
function getMeaningFromDeclaration ( node : Declaration ) : SearchMeaning {
2737
2816
switch ( node . kind ) {
2738
2817
case SyntaxKind . Parameter :
@@ -2869,40 +2948,38 @@ module ts {
2869
2948
}
2870
2949
return meaning ;
2871
2950
}
2951
+ }
2872
2952
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 ( ) ;
2878
2956
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
+ }
2902
2961
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 ;
2904
2979
}
2905
2980
}
2981
+
2982
+ return false ;
2906
2983
}
2907
2984
2908
2985
/// Syntactic features
0 commit comments