Skip to content

Commit 20392de

Browse files
committed
Merge pull request #971 from Microsoft/fixResolveName
Fix the resolveName function
2 parents 290e43b + d4673f9 commit 20392de

File tree

1 file changed

+70
-64
lines changed

1 file changed

+70
-64
lines changed

src/compiler/checker.ts

Lines changed: 70 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)