(node)
| 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) { |
no test coverage detected