Binder Container
AST nodeはContainerになる可能性もあります。これは、Nodeとそれに関連するSymbolが持つSymbolTablesの種類が決定します。Containerは抽象的な概念です(つまり、関連するデータ構造はありません)。この概念は、いくつかのものによって駆動されます。1つはContainerFlagsのenumです。関数getContainerFlags(binder.tsにあります)がこのフラグを駆動します。それを下記に示します:
function getContainerFlags(node: Node): ContainerFlags {
switch (node.kind) {
case SyntaxKind.ClassExpression:
case SyntaxKind.ClassDeclaration:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.EnumDeclaration:
case SyntaxKind.TypeLiteral:
case SyntaxKind.ObjectLiteralExpression:
return ContainerFlags.IsContainer;
case SyntaxKind.CallSignature:
case SyntaxKind.ConstructSignature:
case SyntaxKind.IndexSignature:
case SyntaxKind.MethodDeclaration:
case SyntaxKind.MethodSignature:
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.Constructor:
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.SourceFile:
case SyntaxKind.TypeAliasDeclaration:
return ContainerFlags.IsContainerWithLocals;
case SyntaxKind.CatchClause:
case SyntaxKind.ForStatement:
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
case SyntaxKind.CaseBlock:
return ContainerFlags.IsBlockScopedContainer;
case SyntaxKind.Block:
// do not treat blocks directly inside a function as a block-scoped-container.
// Locals that reside in this block should go to the function locals. Otherwise 'x'
// would not appear to be a redeclaration of a block scoped local in the following
// example:
//
// function foo() {
// var x;
// let x;
// }
//
// If we placed 'var x' into the function locals and 'let x' into the locals of
// the block, then there would be no collision.
//
// By not creating a new block-scoped-container here, we ensure that both 'var x'
// and 'let x' go into the Function-container's locals, and we do get a collision
// conflict.
return isFunctionLike(node.parent) ? ContainerFlags.None : ContainerFlags.IsBlockScopedContainer;
}
return ContainerFlags.None;
}これはBinderのbindChildren関数から_のみ_呼び出され、nodeをcontainerとして、もしくは、blockScopedContainerとして設定します。これはgetContainerFlags関数の評価に依存します。bindChildrenを以下に示します:
Binder関数のセクションから思い出されるようにbind関数からbindChildrenが呼び出されます。だから我々は再帰的なbindingの設定が行えます。つまり、bindは、bindChildrenを呼び出し、それはそれぞれの子に対してbindを呼び出します。
最終更新
役に立ちましたか?