@@ -306,80 +306,49 @@ module ts {
306306 // return undefined if we can't find a symbol.
307307 }
308308
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+
311314 var result : Symbol ;
312315 var lastLocation : Node ;
316+ var propertyWithInvalidInitializer : Node ;
317+ var errorLocation = location ;
313318
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 ) {
351320 // Locals of a source file are not in scope (because they get merged into the global symbol table)
352321 if ( location . locals && ! isGlobalSourceFile ( location ) ) {
353322 if ( result = getSymbol ( location . locals , name , meaning ) ) {
354- return returnResolvedSymbol ( result ) ;
323+ break loop ;
355324 }
356325 }
357326 switch ( location . kind ) {
358327 case SyntaxKind . SourceFile :
359328 if ( ! isExternalModule ( < SourceFile > location ) ) break ;
360329 case SyntaxKind . ModuleDeclaration :
361330 if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . ModuleMember ) ) {
362- return returnResolvedSymbol ( result ) ;
331+ break loop ;
363332 }
364333 break ;
365334 case SyntaxKind . EnumDeclaration :
366335 if ( result = getSymbol ( getSymbolOfNode ( location ) . exports , name , meaning & SymbolFlags . EnumMember ) ) {
367- return returnResolvedSymbol ( result ) ;
336+ break loop ;
368337 }
369338 break ;
370339 case SyntaxKind . Property :
371340 // TypeScript 1.0 spec (April 2014): 8.4.1
372341 // Initializer expressions for instance member variables are evaluated in the scope
373342 // 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
375344 // by the same name as a constructor parameter or local variable are inaccessible
376345 // in initializer expressions for instance member variables.
377346 if ( location . parent . kind === SyntaxKind . ClassDeclaration && ! ( location . flags & NodeFlags . Static ) ) {
378347 var ctor = findConstructorDeclaration ( < ClassDeclaration > location . parent ) ;
379348 if ( ctor && ctor . locals ) {
380349 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 ;
383352 }
384353 }
385354 }
@@ -389,14 +358,12 @@ module ts {
389358 if ( result = getSymbol ( getSymbolOfNode ( location ) . members , name , meaning & SymbolFlags . Type ) ) {
390359 if ( lastLocation && lastLocation . flags & NodeFlags . Static ) {
391360 // 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.
394363 error ( errorLocation , Diagnostics . Static_members_cannot_reference_class_type_parameters ) ;
395364 return undefined ;
396365 }
397- else {
398- return returnResolvedSymbol ( result ) ;
399- }
366+ break loop;
400367 }
401368 break ;
402369 case SyntaxKind . Method :
@@ -406,33 +373,74 @@ module ts {
406373 case SyntaxKind . FunctionDeclaration :
407374 case SyntaxKind . ArrowFunction :
408375 if ( name === "arguments" ) {
409- return returnResolvedSymbol ( argumentsSymbol ) ;
376+ result = argumentsSymbol ;
377+ break loop;
410378 }
411379 break ;
412380 case SyntaxKind . FunctionExpression :
413381 if ( name === "arguments" ) {
414- return returnResolvedSymbol ( argumentsSymbol ) ;
382+ result = argumentsSymbol ;
383+ break loop;
415384 }
416385 var id = ( < FunctionExpression > location ) . name ;
417386 if ( id && name === id . text ) {
418- return returnResolvedSymbol ( location . symbol ) ;
387+ result = location . symbol ;
388+ break loop;
419389 }
420390 break ;
421391 case SyntaxKind . CatchBlock :
422392 var id = ( < CatchBlock > location ) . variable ;
423393 if ( name === id . text ) {
424- return returnResolvedSymbol ( location . symbol ) ;
394+ result = location . symbol ;
395+ break loop;
425396 }
426397 break ;
427398 }
428399 lastLocation = location ;
429400 location = location . parent ;
430401 }
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 ;
433412 }
434413
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 ;
436444 }
437445
438446 function resolveImport ( symbol : Symbol ) : Symbol {
@@ -491,8 +499,7 @@ module ts {
491499 // Resolves a qualified name and any involved import aliases
492500 function resolveEntityName ( location : Node , name : EntityName , meaning : SymbolFlags ) : Symbol {
493501 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 ) ;
496503 if ( ! symbol ) {
497504 return ;
498505 }
@@ -589,7 +596,7 @@ module ts {
589596 }
590597 if ( node . exportName . text ) {
591598 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 ) ;
593600 }
594601 }
595602 symbolLinks . exportAssignSymbol = exportSymbol || unknownSymbol ;
@@ -960,13 +967,12 @@ module ts {
960967
961968 function isImportDeclarationEntityNameReferenceDeclarationVisibile ( entityName : EntityName ) : SymbolAccessiblityResult {
962969 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 ) ;
965971 // Verify if the symbol is accessible
966972 var hasNamespaceDeclarationsVisibile = hasVisibleDeclarations ( symbolOfNameSpace ) ;
967973 return hasNamespaceDeclarationsVisibile ?
968974 { accessibility : SymbolAccessibility . Accessible , aliasesToMakeVisible : hasNamespaceDeclarationsVisibile . aliasesToMakeVisible } :
969- { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : firstIdentifierName } ;
975+ { accessibility : SymbolAccessibility . NotAccessible , errorSymbolName : identifierToString ( < Identifier > firstIdentifier ) } ;
970976 }
971977
972978 function releaseStringWriter ( writer : StringSymbolWriter ) {
@@ -4055,7 +4061,7 @@ module ts {
40554061 function getResolvedSymbol ( node : Identifier ) : Symbol {
40564062 var links = getNodeLinks ( node ) ;
40574063 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 ;
40594065 }
40604066 return links . resolvedSymbol ;
40614067 }
0 commit comments