MCPcopy Index your code
hub / github.com/nodejs/node / checkVarDeclaredNamesNotShadowed

Function checkVarDeclaredNamesNotShadowed

test/fixtures/snapshot/typescript.js:82426–82490  ·  view source on GitHub ↗
(node)

Source from the content-addressed store, hash-verified

82424 }
82425 }
82426 function checkVarDeclaredNamesNotShadowed(node) {
82427 // - ScriptBody : StatementList
82428 // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
82429 // also occurs in the VarDeclaredNames of StatementList.
82430 // - Block : { StatementList }
82431 // It is a Syntax Error if any element of the LexicallyDeclaredNames of StatementList
82432 // also occurs in the VarDeclaredNames of StatementList.
82433 // Variable declarations are hoisted to the top of their function scope. They can shadow
82434 // block scoped declarations, which bind tighter. this will not be flagged as duplicate definition
82435 // by the binder as the declaration scope is different.
82436 // A non-initialized declaration is a no-op as the block declaration will resolve before the var
82437 // declaration. the problem is if the declaration has an initializer. this will act as a write to the
82438 // block declared value. this is fine for let, but not const.
82439 // Only consider declarations with initializers, uninitialized const declarations will not
82440 // step on a let/const variable.
82441 // Do not consider const and const declarations, as duplicate block-scoped declarations
82442 // are handled by the binder.
82443 // We are only looking for const declarations that step on let\const declarations from a
82444 // different scope. e.g.:
82445 // {
82446 // const x = 0; // localDeclarationSymbol obtained after name resolution will correspond to this declaration
82447 // const x = 0; // symbol for this declaration will be 'symbol'
82448 // }
82449 // skip block-scoped variables and parameters
82450 if ((ts.getCombinedNodeFlags(node) & 3 /* NodeFlags.BlockScoped */) !== 0 || ts.isParameterDeclaration(node)) {
82451 return;
82452 }
82453 // skip variable declarations that don't have initializers
82454 // NOTE: in ES6 spec initializer is required in variable declarations where name is binding pattern
82455 // so we'll always treat binding elements as initialized
82456 if (node.kind === 254 /* SyntaxKind.VariableDeclaration */ && !node.initializer) {
82457 return;
82458 }
82459 var symbol = getSymbolOfNode(node);
82460 if (symbol.flags & 1 /* SymbolFlags.FunctionScopedVariable */) {
82461 if (!ts.isIdentifier(node.name))
82462 return ts.Debug.fail();
82463 var localDeclarationSymbol = resolveName(node, node.name.escapedText, 3 /* SymbolFlags.Variable */, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false);
82464 if (localDeclarationSymbol &&
82465 localDeclarationSymbol !== symbol &&
82466 localDeclarationSymbol.flags & 2 /* SymbolFlags.BlockScopedVariable */) {
82467 if (getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol) & 3 /* NodeFlags.BlockScoped */) {
82468 var varDeclList = ts.getAncestor(localDeclarationSymbol.valueDeclaration, 255 /* SyntaxKind.VariableDeclarationList */);
82469 var container = varDeclList.parent.kind === 237 /* SyntaxKind.VariableStatement */ && varDeclList.parent.parent
82470 ? varDeclList.parent.parent
82471 : undefined;
82472 // names of block-scoped and function scoped variables can collide only
82473 // if block scoped variable is defined in the function\module\source file scope (because of variable hoisting)
82474 var namesShareScope = container &&
82475 (container.kind === 235 /* SyntaxKind.Block */ && ts.isFunctionLike(container.parent) ||
82476 container.kind === 262 /* SyntaxKind.ModuleBlock */ ||
82477 container.kind === 261 /* SyntaxKind.ModuleDeclaration */ ||
82478 container.kind === 305 /* SyntaxKind.SourceFile */);
82479 // here we know that function scoped variable is shadowed by block scoped one
82480 // if they are defined in the same scope - binder has already reported redeclaration error
82481 // otherwise if variable has an initializer - show error that initialization will fail
82482 // since LHS will be block scoped name instead of function scoped
82483 if (!namesShareScope) {

Callers 1

Calls 6

getSymbolOfNodeFunction · 0.85
resolveNameFunction · 0.85
symbolToStringFunction · 0.85
errorFunction · 0.70
failMethod · 0.45

Tested by

no test coverage detected