@@ -19,6 +19,8 @@ module ts {
1919 return isExternalModule ( sourceFile ) || isDeclarationFile ( sourceFile ) ;
2020 }
2121
22+ // flag enum used to request and track usages of few dedicated temp variables
23+ // enum values are used to set/check bit values and thus should not have bit collisions.
2224 const enum TempVariableKind {
2325 auto = 0 ,
2426 _i = 1 ,
@@ -216,7 +218,7 @@ module ts {
216218 // _i;
217219 // }
218220 // we should be able to detect if let _i was shadowed by some temp variable that was allocated in scope
219- function hasConflictsWithTempVariables ( name : string ) : boolean {
221+ function nameConflictsWithSomeTempVariable ( name : string ) : boolean {
220222 // temp variable names always start with '_'
221223 if ( name . length < 2 || name . charCodeAt ( 0 ) !== CharacterCodes . _ ) {
222224 return false ;
@@ -242,7 +244,12 @@ module ts {
242244 }
243245 }
244246
247+ // This function generates a name using the following pattern:
245248 // _a .. _h, _j ... _z, _0, _1, ...
249+ // It is guaranteed that generated name will not shadow any existing user-defined names,
250+ // however it can hide another name generated by this function higher in the scope.
251+ // NOTE: names generated by 'makeTempVariableName' and 'makeUniqueName' will never conflict.
252+ // see comment for 'makeTempVariableName' for more information.
246253 function makeTempVariableName ( location : Node , tempVariableKind : TempVariableKind ) : string {
247254 let tempName : string ;
248255 if ( tempVariableKind !== TempVariableKind . auto && ! ( predefinedTempsInUse & tempVariableKind ) ) {
@@ -272,8 +279,17 @@ module ts {
272279 return tempName ;
273280 }
274281
275- // unique names always end with _<number>
276- // generated unique names: name_1, name_2...
282+ // Generates a name that is unique within current file and does not collide with
283+ // any names in global scope.
284+ // NOTE: names generated by 'makeTempVariableName' and 'makeUniqueName' will never conflict
285+ // because of the way how these names are generated
286+ // - makeUniqueName builds a name by picking a base name (which should not be empty string)
287+ // and appending suffix '_<number>'
288+ // - makeTempVariableName creates a name using the following pattern:
289+ // _a .. _h, _j ... _z, _0, _1, ...
290+ // This means that names from 'makeTempVariableName' will have only one underscore at the beginning
291+ // and names from 'makeUniqieName' will have at least one underscore in the middle
292+ // so they will never collide.
277293 function makeUniqueName ( baseName : string ) : string {
278294 Debug . assert ( ! ! baseName ) ;
279295
@@ -2787,8 +2803,9 @@ module ts {
27872803 let list = getAncestor ( node , SyntaxKind . VariableDeclarationList ) ;
27882804 if ( list . parent . kind === SyntaxKind . VariableStatement ) {
27892805 let isSourceFileLevelBinding = list . parent . parent . kind === SyntaxKind . SourceFile ;
2790- let isModuleLevelBinding = list . parent . parent . kind === SyntaxKind . ModuleDeclaration ;
2791- let isFunctionLevelBinding = isFunctionLike ( list . parent . parent ) ;
2806+ let isModuleLevelBinding = list . parent . parent . kind === SyntaxKind . ModuleBlock ;
2807+ let isFunctionLevelBinding =
2808+ list . parent . parent . kind === SyntaxKind . Block && isFunctionLike ( list . parent . parent . parent ) ;
27922809 if ( isSourceFileLevelBinding || isModuleLevelBinding || isFunctionLevelBinding ) {
27932810 return ;
27942811 }
@@ -2801,7 +2818,7 @@ module ts {
28012818
28022819 var hasConflictsInEnclosingScope =
28032820 ! resolver . isUnknownIdentifier ( parent , ( < Identifier > node ) . text ) ||
2804- hasConflictsWithTempVariables ( ( < Identifier > node ) . text ) ;
2821+ nameConflictsWithSomeTempVariable ( ( < Identifier > node ) . text ) ;
28052822
28062823 if ( hasConflictsInEnclosingScope ) {
28072824 let variableId = resolver . getBlockScopedVariableId ( < Identifier > node ) ;
0 commit comments