@@ -2398,42 +2398,51 @@ module ts {
2398
2398
}
2399
2399
2400
2400
/// Completion
2401
- function getValidCompletionEntryDisplayName ( symbol : Symbol , target : ScriptTarget ) : string {
2401
+ function getCompletionEntryDisplayName ( symbol : Symbol , target : ScriptTarget , performCharacterChecks : boolean ) : string {
2402
2402
let displayName = symbol . getName ( ) ;
2403
- if ( displayName && displayName . length > 0 ) {
2404
- let firstCharCode = displayName . charCodeAt ( 0 ) ;
2405
- // First check of the displayName is not external module; if it is an external module, it is not valid entry
2406
- if ( ( symbol . flags & SymbolFlags . Namespace ) && ( firstCharCode === CharacterCodes . singleQuote || firstCharCode === CharacterCodes . doubleQuote ) ) {
2407
- // If the symbol is external module, don't show it in the completion list
2408
- // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there)
2409
- return undefined ;
2410
- }
2403
+ if ( ! displayName ) {
2404
+ return undefined ;
2405
+ }
2411
2406
2412
- if ( displayName && displayName . length >= 2 && firstCharCode === displayName . charCodeAt ( displayName . length - 1 ) &&
2413
- ( firstCharCode === CharacterCodes . singleQuote || firstCharCode === CharacterCodes . doubleQuote ) ) {
2414
- // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
2415
- // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
2416
- displayName = displayName . substring ( 1 , displayName . length - 1 ) ;
2417
- }
2407
+ let firstCharCode = displayName . charCodeAt ( 0 ) ;
2408
+ // First check of the displayName is not external module; if it is an external module, it is not valid entry
2409
+ if ( ( symbol . flags & SymbolFlags . Namespace ) && ( firstCharCode === CharacterCodes . singleQuote || firstCharCode === CharacterCodes . doubleQuote ) ) {
2410
+ // If the symbol is external module, don't show it in the completion list
2411
+ // (i.e declare module "http" { let x; } | // <= request completion here, "http" should not be there)
2412
+ return undefined ;
2413
+ }
2418
2414
2419
- let isValid = isIdentifierStart ( displayName . charCodeAt ( 0 ) , target ) ;
2420
- for ( let i = 1 , n = displayName . length ; isValid && i < n ; i ++ ) {
2421
- isValid = isIdentifierPart ( displayName . charCodeAt ( i ) , target ) ;
2415
+ if ( displayName && displayName . length >= 2 && firstCharCode === displayName . charCodeAt ( displayName . length - 1 ) &&
2416
+ ( firstCharCode === CharacterCodes . singleQuote || firstCharCode === CharacterCodes . doubleQuote ) ) {
2417
+ // If the user entered name for the symbol was quoted, removing the quotes is not enough, as the name could be an
2418
+ // invalid identifier name. We need to check if whatever was inside the quotes is actually a valid identifier name.
2419
+ displayName = displayName . substring ( 1 , displayName . length - 1 ) ;
2420
+ }
2421
+
2422
+ if ( ! displayName ) {
2423
+ return undefined ;
2424
+ }
2425
+
2426
+ if ( performCharacterChecks ) {
2427
+ if ( ! isIdentifierStart ( displayName . charCodeAt ( 0 ) , target ) ) {
2428
+ return undefined ;
2422
2429
}
2423
2430
2424
- if ( isValid ) {
2425
- return unescapeIdentifier ( displayName ) ;
2431
+ for ( let i = 1 , n = displayName . length ; i < n ; i ++ ) {
2432
+ if ( ! isIdentifierPart ( displayName . charCodeAt ( i ) , target ) ) {
2433
+ return undefined ;
2434
+ }
2426
2435
}
2427
2436
}
2428
2437
2429
- return undefined ;
2438
+ return unescapeIdentifier ( displayName ) ;
2430
2439
}
2431
2440
2432
2441
function createCompletionEntry ( symbol : Symbol , typeChecker : TypeChecker , location : Node ) : CompletionEntry {
2433
2442
// Try to get a valid display name for this symbol, if we could not find one, then ignore it.
2434
2443
// We would like to only show things that can be added after a dot, so for instance numeric properties can
2435
2444
// not be accessed with a dot (a.1 <- invalid)
2436
- let displayName = getValidCompletionEntryDisplayName ( symbol , program . getCompilerOptions ( ) . target ) ;
2445
+ let displayName = getCompletionEntryDisplayName ( symbol , program . getCompilerOptions ( ) . target , /*performCharacterChecks:*/ true ) ;
2437
2446
if ( ! displayName ) {
2438
2447
return undefined ;
2439
2448
}
@@ -2449,26 +2458,7 @@ module ts {
2449
2458
} ;
2450
2459
}
2451
2460
2452
- // If symbolName is undefined, all symbols at the specified are returned. If symbolName
2453
- // is not undefined, then the first symbol with that name at the specified position
2454
- // will be returned. Calling without symbolName is useful when you want the entire
2455
- // list of symbols (like for getCompletionsAtPosition). Calling with a symbolName is
2456
- // useful when you want information about a single symbol (like for getCompletionEntryDetails).
2457
- function getCompletionData ( fileName : string , position : number , symbolName ?: string ) {
2458
- let result = getCompletionDataWorker ( fileName , position , symbolName ) ;
2459
- if ( ! result ) {
2460
- return undefined ;
2461
- }
2462
-
2463
- if ( result . symbols && symbolName ) {
2464
- var target = program . getCompilerOptions ( ) . target ;
2465
- result . symbols = filter ( result . symbols , s => getValidCompletionEntryDisplayName ( s , target ) === symbolName ) ;
2466
- }
2467
-
2468
- return result ;
2469
- }
2470
-
2471
- function getCompletionDataWorker ( fileName : string , position : number , symbolName : string ) {
2461
+ function getCompletionData ( fileName : string , position : number ) {
2472
2462
let syntacticStart = new Date ( ) . getTime ( ) ;
2473
2463
let sourceFile = getValidSourceFile ( fileName ) ;
2474
2464
@@ -2600,11 +2590,7 @@ module ts {
2600
2590
let scopeNode = getScopeNode ( previousToken , position , sourceFile ) ;
2601
2591
let symbolMeanings = SymbolFlags . Type | SymbolFlags . Value | SymbolFlags . Namespace | SymbolFlags . Alias ;
2602
2592
2603
- // Filter down to the symbol that matches the symbolName if we were given one.
2604
- let predicate = symbolName !== undefined
2605
- ? ( s : Symbol ) => getValidCompletionEntryDisplayName ( s , target ) === symbolName
2606
- : undefined ;
2607
- symbols = typeInfoResolver . getSymbolsInScope ( scopeNode , symbolMeanings , predicate ) ;
2593
+ symbols = typeInfoResolver . getSymbolsInScope ( scopeNode , symbolMeanings ) ;
2608
2594
}
2609
2595
}
2610
2596
@@ -2955,12 +2941,16 @@ module ts {
2955
2941
function getCompletionEntryDetails ( fileName : string , position : number , entryName : string ) : CompletionEntryDetails {
2956
2942
synchronizeHostData ( ) ;
2957
2943
2958
- // Look up a completion symbol with this name .
2959
- let completionData = getCompletionData ( fileName , position , entryName ) ;
2944
+ // Compute all the completion symbols again .
2945
+ let completionData = getCompletionData ( fileName , position ) ;
2960
2946
if ( completionData ) {
2961
2947
let { symbols, location } = completionData ;
2962
- if ( symbols && symbols . length > 0 ) {
2963
- let symbol = symbols [ 0 ] ;
2948
+
2949
+ // Find the symbol with the matching entry name.
2950
+ let target = program . getCompilerOptions ( ) . target ;
2951
+ let symbol = forEach ( symbols , s => getCompletionEntryDisplayName ( s , target , /*performCharacterChecks:*/ false ) === entryName ? s : undefined ) ;
2952
+
2953
+ if ( symbol ) {
2964
2954
let displayPartsDocumentationsAndSymbolKind = getSymbolDisplayPartsDocumentationAndSymbolKind ( symbol , getValidSourceFile ( fileName ) , location , typeInfoResolver , location , SemanticMeaning . All ) ;
2965
2955
return {
2966
2956
name : entryName ,
0 commit comments