@@ -306,80 +306,49 @@ module ts {
306
306
// return undefined if we can't find a symbol.
307
307
}
308
308
309
- function resolveName ( location : Node , name : string , meaning : SymbolFlags , nameNotFoundMessage : DiagnosticMessage , nameArg : string ) : Symbol {
310
- var errorLocation = location ;
309
+ // Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and
310
+ // the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with
311
+ // the given name can be found.
312
+ function resolveName ( location : Node , name : string , meaning : SymbolFlags , nameNotFoundMessage : DiagnosticMessage , nameArg : string | Identifier ) : Symbol {
313
+
311
314
var result : Symbol ;
312
315
var lastLocation : Node ;
316
+ var propertyWithInvalidInitializer : Node ;
317
+ var errorLocation = location ;
313
318
314
- var memberWithInitializerThatReferencesIdentifierFromConstructor : Node ;
315
-
316
- function returnResolvedSymbol ( s : Symbol ) {
317
- // we've seen member with initializer that references identifier defined in constructor during the search.
318
- // if this was the only result with given name then just report default 'nameNotFound' message.
319
- // however if we met something else that was 'shadowed' by the identifier in constructor - report more specific error
320
- if ( s && memberWithInitializerThatReferencesIdentifierFromConstructor ) {
321
- var propertyName = ( < PropertyDeclaration > memberWithInitializerThatReferencesIdentifierFromConstructor ) . name ;
322
- error ( errorLocation , Diagnostics . Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor , identifierToString ( propertyName ) , nameArg ) ;
323
- return undefined ;
324
- }
325
- if ( ! s && nameNotFoundMessage ) {
326
- error ( errorLocation , nameNotFoundMessage , nameArg ) ;
327
- }
328
-
329
- if ( s && s . flags & SymbolFlags . BlockScopedVariable ) {
330
- // Block-scoped variables can not be used before their definition
331
- var declaration = forEach ( s . declarations , d => d . flags & NodeFlags . BlockScoped ? d : undefined ) ;
332
- Debug . assert ( declaration , "Block-scoped variable declaration is undefined" ) ;
333
- var declarationSourceFile = getSourceFileOfNode ( declaration ) ;
334
- var referenceSourceFile = getSourceFileOfNode ( errorLocation ) ;
335
- if ( declarationSourceFile === referenceSourceFile ) {
336
- if ( declaration . pos > errorLocation . pos ) {
337
- error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
338
- }
339
- }
340
- else if ( compilerOptions . out ) {
341
- var sourceFiles = program . getSourceFiles ( ) ;
342
- if ( sourceFiles . indexOf ( referenceSourceFile ) < sourceFiles . indexOf ( declarationSourceFile ) ) {
343
- error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
344
- }
345
- }
346
- }
347
- return s ;
348
- }
349
-
350
- while ( location ) {
319
+ loop: while ( location ) {
351
320
// Locals of a source file are not in scope (because they get merged into the global symbol table)
352
321
if ( location . locals && ! isGlobalSourceFile ( location ) ) {
353
322
if ( result = getSymbol ( location . locals , name , meaning ) ) {
354
- return returnResolvedSymbol ( result ) ;
323
+ break loop ;
355
324
}
356
325
}
357
326
switch ( location . kind ) {
358
327
case SyntaxKind . SourceFile :
359
328
if ( ! isExternalModule ( < SourceFile > location ) ) break ;
360
329
case SyntaxKind . ModuleDeclaration :
361
330
if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . ModuleMember ) ) {
362
- return returnResolvedSymbol ( result ) ;
331
+ break loop ;
363
332
}
364
333
break ;
365
334
case SyntaxKind . EnumDeclaration :
366
335
if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . EnumMember ) ) {
367
- return returnResolvedSymbol ( result ) ;
336
+ break loop ;
368
337
}
369
338
break ;
370
339
case SyntaxKind . Property :
371
340
// TypeScript 1.0 spec (April 2014): 8.4.1
372
341
// Initializer expressions for instance member variables are evaluated in the scope
373
342
// of the class constructor body but are not permitted to reference parameters or
374
- // local variables of the constructor.This effectively means that entities from outer scopes
343
+ // local variables of the constructor. This effectively means that entities from outer scopes
375
344
// by the same name as a constructor parameter or local variable are inaccessible
376
345
// in initializer expressions for instance member variables.
377
346
if ( location . parent . kind === SyntaxKind . ClassDeclaration && ! ( location . flags & NodeFlags . Static ) ) {
378
347
var ctor = findConstructorDeclaration ( < ClassDeclaration > location . parent ) ;
379
348
if ( ctor && ctor . locals ) {
380
349
if ( getSymbol ( ctor . locals , name , meaning & SymbolFlags . Value ) ) {
381
- // save the property node - later it will be used by 'returnResolvedSymbol' to report appropriate error
382
- memberWithInitializerThatReferencesIdentifierFromConstructor = location ;
350
+ // Remember the property node, it will be used later to report appropriate error
351
+ propertyWithInvalidInitializer = location ;
383
352
}
384
353
}
385
354
}
@@ -389,14 +358,12 @@ module ts {
389
358
if ( result = getSymbol ( getSymbolOfNode ( location ) . members , name , meaning & SymbolFlags . Type ) ) {
390
359
if ( lastLocation && lastLocation . flags & NodeFlags . Static ) {
391
360
// TypeScript 1.0 spec (April 2014): 3.4.1
392
- // The scope of a type parameter extends over the entire declaration
393
- // with which the type parameter list is associated, with the exception of static member declarations in classes.
361
+ // The scope of a type parameter extends over the entire declaration with which the type
362
+ // parameter list is associated, with the exception of static member declarations in classes.
394
363
error ( errorLocation , Diagnostics . Static_members_cannot_reference_class_type_parameters ) ;
395
364
return undefined ;
396
365
}
397
- else {
398
- return returnResolvedSymbol ( result ) ;
399
- }
366
+ break loop;
400
367
}
401
368
break ;
402
369
case SyntaxKind . Method :
@@ -406,33 +373,74 @@ module ts {
406
373
case SyntaxKind . FunctionDeclaration :
407
374
case SyntaxKind . ArrowFunction :
408
375
if ( name === "arguments" ) {
409
- return returnResolvedSymbol ( argumentsSymbol ) ;
376
+ result = argumentsSymbol ;
377
+ break loop;
410
378
}
411
379
break ;
412
380
case SyntaxKind . FunctionExpression :
413
381
if ( name === "arguments" ) {
414
- return returnResolvedSymbol ( argumentsSymbol ) ;
382
+ result = argumentsSymbol ;
383
+ break loop;
415
384
}
416
385
var id = ( < FunctionExpression > location ) . name ;
417
386
if ( id && name === id . text ) {
418
- return returnResolvedSymbol ( location . symbol ) ;
387
+ result = location . symbol ;
388
+ break loop;
419
389
}
420
390
break ;
421
391
case SyntaxKind . CatchBlock :
422
392
var id = ( < CatchBlock > location ) . variable ;
423
393
if ( name === id . text ) {
424
- return returnResolvedSymbol ( location . symbol ) ;
394
+ result = location . symbol ;
395
+ break loop;
425
396
}
426
397
break ;
427
398
}
428
399
lastLocation = location ;
429
400
location = location . parent ;
430
401
}
431
- if ( result = getSymbol ( globals , name , meaning ) ) {
432
- return returnResolvedSymbol ( result ) ;
402
+
403
+ if ( ! result ) {
404
+ result = getSymbol ( globals , name , meaning ) ;
405
+ }
406
+
407
+ if ( ! result ) {
408
+ if ( nameNotFoundMessage ) {
409
+ error ( errorLocation , nameNotFoundMessage , typeof nameArg === "string" ? nameArg : identifierToString ( nameArg ) ) ;
410
+ }
411
+ return undefined ;
433
412
}
434
413
435
- return returnResolvedSymbol ( undefined ) ;
414
+ // Perform extra checks only if error reporting was requested
415
+ if ( nameNotFoundMessage ) {
416
+ if ( propertyWithInvalidInitializer ) {
417
+ // We have a match, but the reference occurred within a property initializer and the identifier also binds
418
+ // to a local variable in the constructor where the code will be emitted.
419
+ var propertyName = ( < PropertyDeclaration > propertyWithInvalidInitializer ) . name ;
420
+ error ( errorLocation , Diagnostics . Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor ,
421
+ identifierToString ( propertyName ) , typeof nameArg === "string" ? nameArg : identifierToString ( nameArg ) ) ;
422
+ return undefined ;
423
+ }
424
+ if ( result . flags & SymbolFlags . BlockScopedVariable ) {
425
+ // Block-scoped variables cannot be used before their definition
426
+ var declaration = forEach ( result . declarations , d => d . flags & NodeFlags . BlockScoped ? d : undefined ) ;
427
+ Debug . assert ( declaration , "Block-scoped variable declaration is undefined" ) ;
428
+ var declarationSourceFile = getSourceFileOfNode ( declaration ) ;
429
+ var referenceSourceFile = getSourceFileOfNode ( errorLocation ) ;
430
+ if ( declarationSourceFile === referenceSourceFile ) {
431
+ if ( declaration . pos > errorLocation . pos ) {
432
+ error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
433
+ }
434
+ }
435
+ else if ( compilerOptions . out ) {
436
+ var sourceFiles = program . getSourceFiles ( ) ;
437
+ if ( sourceFiles . indexOf ( referenceSourceFile ) < sourceFiles . indexOf ( declarationSourceFile ) ) {
438
+ error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
439
+ }
440
+ }
441
+ }
442
+ }
443
+ return result ;
436
444
}
437
445
438
446
function resolveImport ( symbol : Symbol ) : Symbol {
@@ -491,8 +499,7 @@ module ts {
491
499
// Resolves a qualified name and any involved import aliases
492
500
function resolveEntityName ( location : Node , name : EntityName , meaning : SymbolFlags ) : Symbol {
493
501
if ( name . kind === SyntaxKind . Identifier ) {
494
- // TODO: Investigate error recovery for symbols not found
495
- var symbol = resolveName ( location , ( < Identifier > name ) . text , meaning , Diagnostics . Cannot_find_name_0 , identifierToString ( < Identifier > name ) ) ;
502
+ var symbol = resolveName ( location , ( < Identifier > name ) . text , meaning , Diagnostics . Cannot_find_name_0 , < Identifier > name ) ;
496
503
if ( ! symbol ) {
497
504
return ;
498
505
}
@@ -589,7 +596,7 @@ module ts {
589
596
}
590
597
if ( node . exportName . text ) {
591
598
var meaning = SymbolFlags . Value | SymbolFlags . Type | SymbolFlags . Namespace ;
592
- var exportSymbol = resolveName ( node , node . exportName . text , meaning , Diagnostics . Cannot_find_name_0 , identifierToString ( node . exportName ) ) ;
599
+ var exportSymbol = resolveName ( node , node . exportName . text , meaning , Diagnostics . Cannot_find_name_0 , node . exportName ) ;
593
600
}
594
601
}
595
602
symbolLinks . exportAssignSymbol = exportSymbol || unknownSymbol ;
@@ -960,13 +967,12 @@ module ts {
960
967
961
968
function isImportDeclarationEntityNameReferenceDeclarationVisibile ( entityName : EntityName ) : SymbolAccessiblityResult {
962
969
var firstIdentifier = getFirstIdentifier ( entityName ) ;
963
- var firstIdentifierName = identifierToString ( < Identifier > firstIdentifier ) ;
964
- var symbolOfNameSpace = resolveName ( entityName . parent , ( < Identifier > firstIdentifier ) . text , SymbolFlags . Namespace , Diagnostics . Cannot_find_name_0 , firstIdentifierName ) ;
970
+ var symbolOfNameSpace = resolveName ( entityName . parent , ( < Identifier > firstIdentifier ) . text , SymbolFlags . Namespace , Diagnostics . Cannot_find_name_0 , firstIdentifier ) ;
965
971
// Verify if the symbol is accessible
966
972
var hasNamespaceDeclarationsVisibile = hasVisibleDeclarations ( symbolOfNameSpace ) ;
967
973
return hasNamespaceDeclarationsVisibile ?
968
974
{ accessibility : SymbolAccessibility . Accessible , aliasesToMakeVisible : hasNamespaceDeclarationsVisibile . aliasesToMakeVisible } :
969
- { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : firstIdentifierName } ;
975
+ { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : identifierToString ( < Identifier > firstIdentifier ) } ;
970
976
}
971
977
972
978
function releaseStringWriter ( writer : StringSymbolWriter ) {
@@ -4055,7 +4061,7 @@ module ts {
4055
4061
function getResolvedSymbol ( node : Identifier ) : Symbol {
4056
4062
var links = getNodeLinks ( node ) ;
4057
4063
if ( ! links . resolvedSymbol ) {
4058
- links . resolvedSymbol = resolveName ( node , node . text , SymbolFlags . Value | SymbolFlags . ExportValue , Diagnostics . Cannot_find_name_0 , identifierToString ( node ) ) || unknownSymbol ;
4064
+ links . resolvedSymbol = resolveName ( node , node . text , SymbolFlags . Value | SymbolFlags . ExportValue , Diagnostics . Cannot_find_name_0 , node ) || unknownSymbol ;
4059
4065
}
4060
4066
return links . resolvedSymbol ;
4061
4067
}
0 commit comments