@@ -307,80 +307,49 @@ module ts {
307307 // return undefined if we can't find a symbol.
308308 }
309309
310- function resolveName ( location : Node , name : string , meaning : SymbolFlags , nameNotFoundMessage : DiagnosticMessage , nameArg : string ) : Symbol {
311- var errorLocation = location ;
310+ // Resolve a given name for a given meaning at a given location. An error is reported if the name was not found and
311+ // the nameNotFoundMessage argument is not undefined. Returns the resolved symbol, or undefined if no symbol with
312+ // the given name can be found.
313+ function resolveName ( location : Node , name : string , meaning : SymbolFlags , nameNotFoundMessage : DiagnosticMessage , nameArg : string | Identifier ) : Symbol {
314+
312315 var result : Symbol ;
313316 var lastLocation : Node ;
317+ var propertyWithInvalidInitializer : Node ;
318+ var errorLocation = location ;
314319
315- var memberWithInitializerThatReferencesIdentifierFromConstructor : Node ;
316-
317- function returnResolvedSymbol ( s : Symbol ) {
318- // we've seen member with initializer that references identifier defined in constructor during the search.
319- // if this was the only result with given name then just report default 'nameNotFound' message.
320- // however if we met something else that was 'shadowed' by the identifier in constructor - report more specific error
321- if ( s && memberWithInitializerThatReferencesIdentifierFromConstructor ) {
322- var propertyName = ( < PropertyDeclaration > memberWithInitializerThatReferencesIdentifierFromConstructor ) . name ;
323- error ( errorLocation , Diagnostics . Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor , identifierToString ( propertyName ) , nameArg ) ;
324- return undefined ;
325- }
326- if ( ! s && nameNotFoundMessage ) {
327- error ( errorLocation , nameNotFoundMessage , nameArg ) ;
328- }
329-
330- if ( s && s . flags & SymbolFlags . BlockScopedVariable ) {
331- // Block-scoped variables can not be used before their definition
332- var declaration = forEach ( s . declarations , d => d . flags & NodeFlags . BlockScoped ? d : undefined ) ;
333- Debug . assert ( declaration , "Block-scoped variable declaration is undefined" ) ;
334- var declarationSourceFile = getSourceFileOfNode ( declaration ) ;
335- var referenceSourceFile = getSourceFileOfNode ( errorLocation ) ;
336- if ( declarationSourceFile === referenceSourceFile ) {
337- if ( declaration . pos > errorLocation . pos ) {
338- error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
339- }
340- }
341- else if ( compilerOptions . out ) {
342- var sourceFiles = program . getSourceFiles ( ) ;
343- if ( sourceFiles . indexOf ( referenceSourceFile ) < sourceFiles . indexOf ( declarationSourceFile ) ) {
344- error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
345- }
346- }
347- }
348- return s ;
349- }
350-
351- while ( location ) {
320+ loop: while ( location ) {
352321 // Locals of a source file are not in scope (because they get merged into the global symbol table)
353322 if ( location . locals && ! isGlobalSourceFile ( location ) ) {
354323 if ( result = getSymbol ( location . locals , name , meaning ) ) {
355- return returnResolvedSymbol ( result ) ;
324+ break loop ;
356325 }
357326 }
358327 switch ( location . kind ) {
359328 case SyntaxKind . SourceFile :
360329 if ( ! isExternalModule ( < SourceFile > location ) ) break ;
361330 case SyntaxKind . ModuleDeclaration :
362331 if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . ModuleMember ) ) {
363- return returnResolvedSymbol ( result ) ;
332+ break loop ;
364333 }
365334 break ;
366335 case SyntaxKind . EnumDeclaration :
367336 if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . EnumMember ) ) {
368- return returnResolvedSymbol ( result ) ;
337+ break loop ;
369338 }
370339 break ;
371340 case SyntaxKind . Property :
372341 // TypeScript 1.0 spec (April 2014): 8.4.1
373342 // Initializer expressions for instance member variables are evaluated in the scope
374343 // of the class constructor body but are not permitted to reference parameters or
375- // local variables of the constructor.This effectively means that entities from outer scopes
344+ // local variables of the constructor. This effectively means that entities from outer scopes
376345 // by the same name as a constructor parameter or local variable are inaccessible
377346 // in initializer expressions for instance member variables.
378347 if ( location . parent . kind === SyntaxKind . ClassDeclaration && ! ( location . flags & NodeFlags . Static ) ) {
379348 var ctor = findConstructorDeclaration ( < ClassDeclaration > location . parent ) ;
380349 if ( ctor && ctor . locals ) {
381350 if ( getSymbol ( ctor . locals , name , meaning & SymbolFlags . Value ) ) {
382- // save the property node - later it will be used by 'returnResolvedSymbol' to report appropriate error
383- memberWithInitializerThatReferencesIdentifierFromConstructor = location ;
351+ // Remember the property node, it will be used later to report appropriate error
352+ propertyWithInvalidInitializer = location ;
384353 }
385354 }
386355 }
@@ -390,14 +359,12 @@ module ts {
390359 if ( result = getSymbol ( getSymbolOfNode ( location ) . members , name , meaning & SymbolFlags . Type ) ) {
391360 if ( lastLocation && lastLocation . flags & NodeFlags . Static ) {
392361 // TypeScript 1.0 spec (April 2014): 3.4.1
393- // The scope of a type parameter extends over the entire declaration
394- // with which the type parameter list is associated, with the exception of static member declarations in classes.
362+ // The scope of a type parameter extends over the entire declaration with which the type
363+ // parameter list is associated, with the exception of static member declarations in classes.
395364 error ( errorLocation , Diagnostics . Static_members_cannot_reference_class_type_parameters ) ;
396365 return undefined ;
397366 }
398- else {
399- return returnResolvedSymbol ( result ) ;
400- }
367+ break loop;
401368 }
402369 break ;
403370 case SyntaxKind . Method :
@@ -407,33 +374,74 @@ module ts {
407374 case SyntaxKind . FunctionDeclaration :
408375 case SyntaxKind . ArrowFunction :
409376 if ( name === "arguments" ) {
410- return returnResolvedSymbol ( argumentsSymbol ) ;
377+ result = argumentsSymbol ;
378+ break loop;
411379 }
412380 break ;
413381 case SyntaxKind . FunctionExpression :
414382 if ( name === "arguments" ) {
415- return returnResolvedSymbol ( argumentsSymbol ) ;
383+ result = argumentsSymbol ;
384+ break loop;
416385 }
417386 var id = ( < FunctionExpression > location ) . name ;
418387 if ( id && name === id . text ) {
419- return returnResolvedSymbol ( location . symbol ) ;
388+ result = location . symbol ;
389+ break loop;
420390 }
421391 break ;
422392 case SyntaxKind . CatchBlock :
423393 var id = ( < CatchBlock > location ) . variable ;
424394 if ( name === id . text ) {
425- return returnResolvedSymbol ( location . symbol ) ;
395+ result = location . symbol ;
396+ break loop;
426397 }
427398 break ;
428399 }
429400 lastLocation = location ;
430401 location = location . parent ;
431402 }
432- if ( result = getSymbol ( globals , name , meaning ) ) {
433- return returnResolvedSymbol ( result ) ;
403+
404+ if ( ! result ) {
405+ result = getSymbol ( globals , name , meaning ) ;
406+ }
407+
408+ if ( ! result ) {
409+ if ( nameNotFoundMessage ) {
410+ error ( errorLocation , nameNotFoundMessage , typeof nameArg === "string" ? nameArg : identifierToString ( nameArg ) ) ;
411+ }
412+ return undefined ;
434413 }
435414
436- return returnResolvedSymbol ( undefined ) ;
415+ // Perform extra checks only if error reporting was requested
416+ if ( nameNotFoundMessage ) {
417+ if ( propertyWithInvalidInitializer ) {
418+ // We have a match, but the reference occurred within a property initializer and the identifier also binds
419+ // to a local variable in the constructor where the code will be emitted.
420+ var propertyName = ( < PropertyDeclaration > propertyWithInvalidInitializer ) . name ;
421+ error ( errorLocation , Diagnostics . Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor ,
422+ identifierToString ( propertyName ) , typeof nameArg === "string" ? nameArg : identifierToString ( nameArg ) ) ;
423+ return undefined ;
424+ }
425+ if ( result . flags & SymbolFlags . BlockScopedVariable ) {
426+ // Block-scoped variables cannot be used before their definition
427+ var declaration = forEach ( result . declarations , d => d . flags & NodeFlags . BlockScoped ? d : undefined ) ;
428+ Debug . assert ( declaration , "Block-scoped variable declaration is undefined" ) ;
429+ var declarationSourceFile = getSourceFileOfNode ( declaration ) ;
430+ var referenceSourceFile = getSourceFileOfNode ( errorLocation ) ;
431+ if ( declarationSourceFile === referenceSourceFile ) {
432+ if ( declaration . pos > errorLocation . pos ) {
433+ error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
434+ }
435+ }
436+ else if ( compilerOptions . out ) {
437+ var sourceFiles = program . getSourceFiles ( ) ;
438+ if ( sourceFiles . indexOf ( referenceSourceFile ) < sourceFiles . indexOf ( declarationSourceFile ) ) {
439+ error ( errorLocation , Diagnostics . Block_scoped_variable_0_used_before_its_declaration , identifierToString ( declaration . name ) ) ;
440+ }
441+ }
442+ }
443+ }
444+ return result ;
437445 }
438446
439447 function resolveImport ( symbol : Symbol ) : Symbol {
@@ -492,8 +500,7 @@ module ts {
492500 // Resolves a qualified name and any involved import aliases
493501 function resolveEntityName ( location : Node , name : EntityName , meaning : SymbolFlags ) : Symbol {
494502 if ( name . kind === SyntaxKind . Identifier ) {
495- // TODO: Investigate error recovery for symbols not found
496- var symbol = resolveName ( location , ( < Identifier > name ) . text , meaning , Diagnostics . Cannot_find_name_0 , identifierToString ( < Identifier > name ) ) ;
503+ var symbol = resolveName ( location , ( < Identifier > name ) . text , meaning , Diagnostics . Cannot_find_name_0 , < Identifier > name ) ;
497504 if ( ! symbol ) {
498505 return ;
499506 }
@@ -590,7 +597,7 @@ module ts {
590597 }
591598 if ( node . exportName . text ) {
592599 var meaning = SymbolFlags . Value | SymbolFlags . Type | SymbolFlags . Namespace ;
593- var exportSymbol = resolveName ( node , node . exportName . text , meaning , Diagnostics . Cannot_find_name_0 , identifierToString ( node . exportName ) ) ;
600+ var exportSymbol = resolveName ( node , node . exportName . text , meaning , Diagnostics . Cannot_find_name_0 , node . exportName ) ;
594601 }
595602 }
596603 symbolLinks . exportAssignSymbol = exportSymbol || unknownSymbol ;
@@ -961,13 +968,12 @@ module ts {
961968
962969 function isImportDeclarationEntityNameReferenceDeclarationVisibile ( entityName : EntityName ) : SymbolAccessiblityResult {
963970 var firstIdentifier = getFirstIdentifier ( entityName ) ;
964- var firstIdentifierName = identifierToString ( < Identifier > firstIdentifier ) ;
965- var symbolOfNameSpace = resolveName ( entityName . parent , ( < Identifier > firstIdentifier ) . text , SymbolFlags . Namespace , Diagnostics . Cannot_find_name_0 , firstIdentifierName ) ;
971+ var symbolOfNameSpace = resolveName ( entityName . parent , ( < Identifier > firstIdentifier ) . text , SymbolFlags . Namespace , Diagnostics . Cannot_find_name_0 , firstIdentifier ) ;
966972 // Verify if the symbol is accessible
967973 var hasNamespaceDeclarationsVisibile = hasVisibleDeclarations ( symbolOfNameSpace ) ;
968974 return hasNamespaceDeclarationsVisibile ?
969975 { accessibility : SymbolAccessibility . Accessible , aliasesToMakeVisible : hasNamespaceDeclarationsVisibile . aliasesToMakeVisible } :
970- { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : firstIdentifierName } ;
976+ { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : identifierToString ( < Identifier > firstIdentifier ) } ;
971977 }
972978
973979 function releaseStringWriter ( writer : StringSymbolWriter ) {
@@ -4114,7 +4120,7 @@ module ts {
41144120 function getResolvedSymbol ( node : Identifier ) : Symbol {
41154121 var links = getNodeLinks ( node ) ;
41164122 if ( ! links . resolvedSymbol ) {
4117- links . resolvedSymbol = resolveName ( node , node . text , SymbolFlags . Value | SymbolFlags . ExportValue , Diagnostics . Cannot_find_name_0 , identifierToString ( node ) ) || unknownSymbol ;
4123+ links . resolvedSymbol = resolveName ( node , node . text , SymbolFlags . Value | SymbolFlags . ExportValue , Diagnostics . Cannot_find_name_0 , node ) || unknownSymbol ;
41184124 }
41194125 return links . resolvedSymbol ;
41204126 }
0 commit comments