2015-02-03 00:30:33 +01:00
//// [parserRealSource8.ts]
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='typescript.ts' />
module TypeScript {
export class AssignScopeContext {
constructor ( public scopeChain : ScopeChain ,
public typeFlow : TypeFlow ,
public modDeclChain : ModuleDeclaration [ ] ) {
}
}
export function pushAssignScope ( scope : SymbolScope ,
context : AssignScopeContext ,
type : Type ,
classType : Type ,
fnc : FuncDecl ) {
var chain = new ScopeChain ( null , context . scopeChain , scope ) ;
chain . thisType = type ;
chain . classType = classType ;
chain . fnc = fnc ;
context . scopeChain = chain ;
}
export function popAssignScope ( context : AssignScopeContext ) {
context . scopeChain = context . scopeChain . previous ;
}
export function instanceCompare ( a : Symbol , b : Symbol ) {
if ( ( ( a == null ) || ( ! a . isInstanceProperty ( ) ) ) ) {
return b ;
}
else {
return a ;
}
}
export function instanceFilterStop ( s : Symbol ) {
return s . isInstanceProperty ( ) ;
}
export class ScopeSearchFilter {
constructor ( public select : ( a : Symbol , b : Symbol ) = > Symbol ,
public stop : ( s : Symbol ) = > boolean ) { }
public result : Symbol = null ;
public reset() {
this . result = null ;
}
public update ( b : Symbol ) : boolean {
this . result = this . select ( this . result , b ) ;
if ( this . result ) {
return this . stop ( this . result ) ;
}
else {
return false ;
}
}
}
export var instanceFilter = new ScopeSearchFilter ( instanceCompare , instanceFilterStop ) ;
export function preAssignModuleScopes ( ast : AST , context : AssignScopeContext ) {
var module Decl = < ModuleDeclaration > ast ;
var memberScope : SymbolTableScope = null ;
var aggScope : SymbolAggregateScope = null ;
if ( module Decl.name && module Decl.mod ) {
module Decl.name.sym = module Decl.mod.symbol ;
}
var mod = module Decl.mod ;
// We're likely here because of error recovery
if ( ! mod ) {
return ;
}
memberScope = new SymbolTableScope ( mod . members , mod . ambientMembers , mod . enclosedTypes , mod . ambientEnclosedTypes , mod . symbol ) ;
mod . memberScope = memberScope ;
context . modDeclChain . push ( module Decl ) ;
context . typeFlow . checker . currentModDecl = module Decl ;
aggScope = new SymbolAggregateScope ( mod . symbol ) ;
aggScope . addParentScope ( memberScope ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
pushAssignScope ( aggScope , context , null , null , null ) ;
mod . containedScope = aggScope ;
if ( mod . symbol ) {
context . typeFlow . addLocalsFromScope ( mod . containedScope , mod . symbol , module Decl.vars , mod . members . privateMembers , true ) ;
}
}
export function preAssignClassScopes ( ast : AST , context : AssignScopeContext ) {
var classDecl = < InterfaceDeclaration > ast ;
var memberScope : SymbolTableScope = null ;
var aggScope : SymbolAggregateScope = null ;
if ( classDecl . name && classDecl . type ) {
classDecl . name . sym = classDecl . type . symbol ;
}
var classType = ast . type ;
if ( classType ) {
var classSym = classType . symbol ;
memberScope = < SymbolTableScope > context . typeFlow . checker . scopeOf ( classType ) ;
aggScope = new SymbolAggregateScope ( classType . symbol ) ;
aggScope . addParentScope ( memberScope ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
classType . containedScope = aggScope ;
classType . memberScope = memberScope ;
var instanceType = classType . instanceType ;
memberScope = < SymbolTableScope > context . typeFlow . checker . scopeOf ( instanceType ) ;
instanceType . memberScope = memberScope ;
aggScope = new SymbolAggregateScope ( instanceType . symbol ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
pushAssignScope ( aggScope , context , instanceType , classType , null ) ;
instanceType . containedScope = aggScope ;
}
else {
ast . type = context . typeFlow . anyType ;
}
}
export function preAssignInterfaceScopes ( ast : AST , context : AssignScopeContext ) {
var interfaceDecl = < InterfaceDeclaration > ast ;
var memberScope : SymbolTableScope = null ;
var aggScope : SymbolAggregateScope = null ;
if ( interfaceDecl . name && interfaceDecl . type ) {
interfaceDecl . name . sym = interfaceDecl . type . symbol ;
}
var interfaceType = ast . type ;
memberScope = < SymbolTableScope > context . typeFlow . checker . scopeOf ( interfaceType ) ;
interfaceType . memberScope = memberScope ;
aggScope = new SymbolAggregateScope ( interfaceType . symbol ) ;
aggScope . addParentScope ( memberScope ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
pushAssignScope ( aggScope , context , null , null , null ) ;
interfaceType . containedScope = aggScope ;
}
export function preAssignWithScopes ( ast : AST , context : AssignScopeContext ) {
var withStmt = < WithStatement > ast ;
var withType = withStmt . type ;
var members = new ScopedMembers ( new DualStringHashTable ( new StringHashTable ( ) , new StringHashTable ( ) ) ) ;
var ambientMembers = new ScopedMembers ( new DualStringHashTable ( new StringHashTable ( ) , new StringHashTable ( ) ) ) ;
var withType = new Type ( ) ;
var withSymbol = new WithSymbol ( withStmt . minChar , context . typeFlow . checker . locationInfo . unitIndex , withType ) ;
withType . members = members ;
withType . ambientMembers = ambientMembers ;
withType . symbol = withSymbol ;
withType . setHasImplementation ( ) ;
withStmt . type = withType ;
var withScope = new TypeScript . SymbolScopeBuilder ( withType . members , withType . ambientMembers , null , null , context . scopeChain . scope , withType . symbol ) ;
pushAssignScope ( withScope , context , null , null , null ) ;
withType . containedScope = withScope ;
}
export function preAssignFuncDeclScopes ( ast : AST , context : AssignScopeContext ) {
var funcDecl = < FuncDecl > ast ;
var container : Symbol = null ;
var localContainer : Symbol = null ;
if ( funcDecl . type ) {
localContainer = ast . type . symbol ;
}
var isStatic = hasFlag ( funcDecl . fncFlags , FncFlags . Static ) ;
var isInnerStatic = isStatic && context . scopeChain . fnc != null ;
// for inner static functions, use the parent's member scope, so local vars cannot be captured
var parentScope = isInnerStatic ? context.scopeChain.fnc.type.memberScope : context.scopeChain.scope ;
// if this is not a method, but enclosed by class, use constructor as
// the enclosing scope
// REVIEW: Some twisted logic here - this needs to be cleaned up once old classes are removed
// - if it's a new class, always use the contained scope, since we initialize the constructor scope below
if ( context . scopeChain . thisType &&
( ! funcDecl . isConstructor || hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) ) {
var instType = context . scopeChain . thisType ;
if ( ! ( instType . typeFlags & TypeFlags . IsClass ) && ! hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) {
if ( ! funcDecl . isMethod ( ) || isStatic ) {
parentScope = instType . constructorScope ;
}
else {
// use constructor scope if a method as well
parentScope = instType . containedScope ;
}
}
else {
if ( context . scopeChain . previous . scope . container &&
context . scopeChain . previous . scope . container . declAST &&
context . scopeChain . previous . scope . container . declAST . nodeType == NodeType . FuncDecl &&
( < FuncDecl > context . scopeChain . previous . scope . container . declAST ) . isConstructor ) {
// if the parent is the class constructor, use the constructor scope
parentScope = instType . constructorScope ;
}
else if ( isStatic && context . scopeChain . classType ) {
parentScope = context . scopeChain . classType . containedScope ;
}
else {
// else, use the contained scope
parentScope = instType . containedScope ;
}
}
container = instType . symbol ;
}
else if ( funcDecl . isConstructor && context . scopeChain . thisType ) {
// sets the container to the class type's symbol (which is shared by the instance type)
container = context . scopeChain . thisType . symbol ;
}
if ( funcDecl . type == null || hasFlag ( funcDecl . type . symbol . flags , SymbolFlags . TypeSetDuringScopeAssignment ) ) {
if ( context . scopeChain . fnc && context . scopeChain . fnc . type ) {
container = context . scopeChain . fnc . type . symbol ;
}
var funcScope = null ;
var outerFnc : FuncDecl = context . scopeChain . fnc ;
var nameText = funcDecl . name ? funcDecl.name.actualText : null ;
var fgSym : TypeSymbol = null ;
if ( isStatic ) {
// In the case of function-nested statics, no member list will have bee initialized for the function, so we need
// to copy it over. We don't set this by default because having a non-null member list will throw off assignment
// compatibility tests
if ( outerFnc . type . members == null && container . getType ( ) . memberScope ) {
outerFnc . type . members = ( < SymbolScopeBuilder > ( < TypeSymbol > container ) . type . memberScope ) . valueMembers ;
}
funcScope = context . scopeChain . fnc . type . memberScope ;
outerFnc . innerStaticFuncs [ outerFnc . innerStaticFuncs . length ] = funcDecl ;
}
else {
if ( ! funcDecl . isConstructor &&
container &&
container . declAST &&
container . declAST . nodeType == NodeType . FuncDecl &&
( < FuncDecl > container . declAST ) . isConstructor &&
! funcDecl . isMethod ( ) ) {
funcScope = context . scopeChain . thisType . constructorScope ; //locals;
}
else {
funcScope = context . scopeChain . scope ;
}
}
// REVIEW: We don't search for another sym for accessors to prevent us from
// accidentally coalescing function signatures with the same name (E.g., a function
// 'f' the outer scope and a setter 'f' in an object literal within that scope)
if ( nameText && nameText != "__missing" && ! funcDecl . isAccessor ( ) ) {
if ( isStatic ) {
fgSym = funcScope . findLocal ( nameText , false , false ) ;
}
else {
// REVIEW: This logic should be symmetric with preCollectClassTypes
fgSym = funcScope . findLocal ( nameText , false , false ) ;
}
}
context . typeFlow . checker . createFunctionSignature ( funcDecl , container ,
funcScope , fgSym , fgSym == null ) ;
// it's a getter or setter for a class property
if ( ! funcDecl . accessorSymbol &&
( funcDecl . fncFlags & FncFlags . ClassMethod ) &&
container &&
( ( ! fgSym || fgSym . declAST . nodeType != NodeType . FuncDecl ) && funcDecl . isAccessor ( ) ) ||
( fgSym && fgSym . isAccessor ( ) ) )
{
funcDecl . accessorSymbol = context . typeFlow . checker . createAccessorSymbol ( funcDecl , fgSym , container . getType ( ) , ( funcDecl . isMethod ( ) && isStatic ) , true , funcScope , container ) ;
}
funcDecl . type . symbol . flags |= SymbolFlags . TypeSetDuringScopeAssignment ;
}
// Set the symbol for functions and their overloads
if ( funcDecl . name && funcDecl . type ) {
funcDecl . name . sym = funcDecl . type . symbol ;
}
// Keep track of the original scope type, because target typing might override
// the "type" member. We need the original "Scope type" for completion list, etc.
funcDecl . scopeType = funcDecl . type ;
// Overloads have no scope, so bail here
if ( funcDecl . isOverload ) {
return ;
}
var funcTable = new StringHashTable ( ) ;
var funcMembers = new ScopedMembers ( new DualStringHashTable ( funcTable , new StringHashTable ( ) ) ) ;
var ambientFuncTable = new StringHashTable ( ) ;
var ambientFuncMembers = new ScopedMembers ( new DualStringHashTable ( ambientFuncTable , new StringHashTable ( ) ) ) ;
var funcStaticTable = new StringHashTable ( ) ;
var funcStaticMembers = new ScopedMembers ( new DualStringHashTable ( funcStaticTable , new StringHashTable ( ) ) ) ;
var ambientFuncStaticTable = new StringHashTable ( ) ;
var ambientFuncStaticMembers = new ScopedMembers ( new DualStringHashTable ( ambientFuncStaticTable , new StringHashTable ( ) ) ) ;
// REVIEW: Is it a problem that this is being set twice for properties and constructors?
funcDecl . unitIndex = context . typeFlow . checker . locationInfo . unitIndex ;
var locals = new SymbolScopeBuilder ( funcMembers , ambientFuncMembers , null , null , parentScope , localContainer ) ;
var statics = new SymbolScopeBuilder ( funcStaticMembers , ambientFuncStaticMembers , null , null , parentScope , null ) ;
if ( funcDecl . isConstructor && context . scopeChain . thisType ) {
context . scopeChain . thisType . constructorScope = locals ;
}
// basically, there are two problems
// - Above, for new classes, we were overwriting the constructor scope with the containing scope. This caused constructor params to be
// in scope everywhere
// - Below, we're setting the contained scope table to the same table we were overwriting the constructor scope with, which we need to
// fish lambda params, etc, out (see funcTable below)
//
// A good first approach to solving this would be to change addLocalsFromScope to take a scope instead of a table, and add to the
// constructor scope as appropriate
funcDecl . symbols = funcTable ;
if ( ! funcDecl . isSpecialFn ( ) ) {
var group = funcDecl . type ;
var signature = funcDecl . signature ;
if ( ! funcDecl . isConstructor ) {
group . containedScope = locals ;
locals . container = group . symbol ;
group . memberScope = statics ;
statics . container = group . symbol ;
}
funcDecl . enclosingFnc = context . scopeChain . fnc ;
group . enclosingType = isStatic ? context.scopeChain.classType : context.scopeChain.thisType ;
// for mapping when type checking
var fgSym = < TypeSymbol > ast . type . symbol ;
if ( ( ( funcDecl . fncFlags & FncFlags . Signature ) == FncFlags . None ) && funcDecl . vars ) {
context . typeFlow . addLocalsFromScope ( locals , fgSym , funcDecl . vars ,
funcTable , false ) ;
context . typeFlow . addLocalsFromScope ( statics , fgSym , funcDecl . statics ,
funcStaticTable , false ) ;
}
if ( signature . parameters ) {
var len = signature . parameters . length ;
for ( var i = 0 ; i < len ; i ++ ) {
var paramSym : ParameterSymbol = signature . parameters [ i ] ;
context . typeFlow . checker . resolveTypeLink ( locals ,
paramSym . parameter . typeLink , true ) ;
}
}
context . typeFlow . checker . resolveTypeLink ( locals , signature . returnType ,
funcDecl . isSignature ( ) ) ;
}
if ( ! funcDecl . isConstructor || hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) {
var thisType = ( funcDecl . isConstructor && hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) ? context.scopeChain.thisType : null ;
pushAssignScope ( locals , context , thisType , null , funcDecl ) ;
}
}
export function preAssignCatchScopes ( ast : AST , context : AssignScopeContext ) {
var catchBlock = < Catch > ast ;
if ( catchBlock . param ) {
var catchTable = new ScopedMembers ( new DualStringHashTable ( new StringHashTable ( ) , new StringHashTable ( ) ) ) ; // REVIEW: Should we be allocating a public table instead of a private one?
var catchLocals = new SymbolScopeBuilder ( catchTable , null , null , null , context . scopeChain . scope ,
context . scopeChain . scope . container ) ;
catchBlock . containedScope = catchLocals ;
pushAssignScope ( catchLocals , context , context . scopeChain . thisType , context . scopeChain . classType , context . scopeChain . fnc ) ;
}
}
export function preAssignScopes ( ast : AST , parent : AST , walker : IAstWalker ) {
var context :AssignScopeContext = walker . state ;
var go = true ;
if ( ast ) {
if ( ast . nodeType == NodeType . List ) {
var list = < ASTList > ast ;
list . enclosingScope = context . scopeChain . scope ;
}
else if ( ast . nodeType == NodeType . ModuleDeclaration ) {
preAssignModuleScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . ClassDeclaration ) {
preAssignClassScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . InterfaceDeclaration ) {
preAssignInterfaceScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . With ) {
preAssignWithScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . FuncDecl ) {
preAssignFuncDeclScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . Catch ) {
preAssignCatchScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . TypeRef ) {
go = false ;
}
}
walker . options . goChildren = go ;
return ast ;
}
export function postAssignScopes ( ast : AST , parent : AST , walker : IAstWalker ) {
var context :AssignScopeContext = walker . state ;
var go = true ;
if ( ast ) {
if ( ast . nodeType == NodeType . ModuleDeclaration ) {
var prevModDecl = < ModuleDeclaration > ast ;
popAssignScope ( context ) ;
context . modDeclChain . pop ( ) ;
if ( context . modDeclChain . length >= 1 ) {
context . typeFlow . checker . currentModDecl = context . modDeclChain [ context . modDeclChain . length - 1 ] ;
}
}
else if ( ast . nodeType == NodeType . ClassDeclaration ) {
popAssignScope ( context ) ;
}
else if ( ast . nodeType == NodeType . InterfaceDeclaration ) {
popAssignScope ( context ) ;
}
else if ( ast . nodeType == NodeType . With ) {
popAssignScope ( context ) ;
}
else if ( ast . nodeType == NodeType . FuncDecl ) {
var funcDecl = < FuncDecl > ast ;
if ( ( ! funcDecl . isConstructor || hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) && ! funcDecl . isOverload ) {
popAssignScope ( context ) ;
}
}
else if ( ast . nodeType == NodeType . Catch ) {
var catchBlock = < Catch > ast ;
if ( catchBlock . param ) {
popAssignScope ( context ) ;
}
}
else {
go = false ;
}
}
walker . options . goChildren = go ;
return ast ;
}
}
//// [parserRealSource8.js]
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
///<reference path='typescript.ts' />
var TypeScript ;
( function ( TypeScript ) {
var AssignScopeContext = ( function ( ) {
function AssignScopeContext ( scopeChain , typeFlow , modDeclChain ) {
this . scopeChain = scopeChain ;
this . typeFlow = typeFlow ;
this . modDeclChain = modDeclChain ;
}
return AssignScopeContext ;
} ) ( ) ;
TypeScript . AssignScopeContext = AssignScopeContext ;
function pushAssignScope ( scope , context , type , classType , fnc ) {
var chain = new ScopeChain ( null , context . scopeChain , scope ) ;
chain . thisType = type ;
chain . classType = classType ;
chain . fnc = fnc ;
context . scopeChain = chain ;
}
TypeScript . pushAssignScope = pushAssignScope ;
function popAssignScope ( context ) {
context . scopeChain = context . scopeChain . previous ;
}
TypeScript . popAssignScope = popAssignScope ;
function instanceCompare ( a , b ) {
if ( ( ( a == null ) || ( ! a . isInstanceProperty ( ) ) ) ) {
return b ;
}
else {
return a ;
}
}
TypeScript . instanceCompare = instanceCompare ;
function instanceFilterStop ( s ) {
return s . isInstanceProperty ( ) ;
}
TypeScript . instanceFilterStop = instanceFilterStop ;
var ScopeSearchFilter = ( function ( ) {
function ScopeSearchFilter ( select , stop ) {
this . select = select ;
this . stop = stop ;
this . result = null ;
}
ScopeSearchFilter . prototype . reset = function ( ) {
this . result = null ;
} ;
ScopeSearchFilter . prototype . update = function ( b ) {
this . result = this . select ( this . result , b ) ;
if ( this . result ) {
return this . stop ( this . result ) ;
}
else {
return false ;
}
} ;
return ScopeSearchFilter ;
} ) ( ) ;
TypeScript . ScopeSearchFilter = ScopeSearchFilter ;
TypeScript . instanceFilter = new ScopeSearchFilter ( instanceCompare , instanceFilterStop ) ;
function preAssignModuleScopes ( ast , context ) {
var module Decl = ast ;
var memberScope = null ;
var aggScope = null ;
if ( module Decl.name && module Decl.mod ) {
module Decl.name.sym = module Decl.mod.symbol ;
}
var mod = module Decl.mod ;
// We're likely here because of error recovery
if ( ! mod ) {
return ;
}
memberScope = new SymbolTableScope ( mod . members , mod . ambientMembers , mod . enclosedTypes , mod . ambientEnclosedTypes , mod . symbol ) ;
mod . memberScope = memberScope ;
context . modDeclChain . push ( module Decl ) ;
context . typeFlow . checker . currentModDecl = module Decl ;
aggScope = new SymbolAggregateScope ( mod . symbol ) ;
aggScope . addParentScope ( memberScope ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
pushAssignScope ( aggScope , context , null , null , null ) ;
mod . containedScope = aggScope ;
if ( mod . symbol ) {
context . typeFlow . addLocalsFromScope ( mod . containedScope , mod . symbol , module Decl.vars , mod . members . privateMembers , true ) ;
}
}
TypeScript . preAssignModuleScopes = preAssignModuleScopes ;
function preAssignClassScopes ( ast , context ) {
var classDecl = ast ;
var memberScope = null ;
var aggScope = null ;
if ( classDecl . name && classDecl . type ) {
classDecl . name . sym = classDecl . type . symbol ;
}
var classType = ast . type ;
if ( classType ) {
var classSym = classType . symbol ;
memberScope = context . typeFlow . checker . scopeOf ( classType ) ;
aggScope = new SymbolAggregateScope ( classType . symbol ) ;
aggScope . addParentScope ( memberScope ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
classType . containedScope = aggScope ;
classType . memberScope = memberScope ;
var instanceType = classType . instanceType ;
memberScope = context . typeFlow . checker . scopeOf ( instanceType ) ;
instanceType . memberScope = memberScope ;
aggScope = new SymbolAggregateScope ( instanceType . symbol ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
pushAssignScope ( aggScope , context , instanceType , classType , null ) ;
instanceType . containedScope = aggScope ;
}
else {
ast . type = context . typeFlow . anyType ;
}
}
TypeScript . preAssignClassScopes = preAssignClassScopes ;
function preAssignInterfaceScopes ( ast , context ) {
var interfaceDecl = ast ;
var memberScope = null ;
var aggScope = null ;
if ( interfaceDecl . name && interfaceDecl . type ) {
interfaceDecl . name . sym = interfaceDecl . type . symbol ;
}
var interfaceType = ast . type ;
memberScope = context . typeFlow . checker . scopeOf ( interfaceType ) ;
interfaceType . memberScope = memberScope ;
aggScope = new SymbolAggregateScope ( interfaceType . symbol ) ;
aggScope . addParentScope ( memberScope ) ;
aggScope . addParentScope ( context . scopeChain . scope ) ;
pushAssignScope ( aggScope , context , null , null , null ) ;
interfaceType . containedScope = aggScope ;
}
TypeScript . preAssignInterfaceScopes = preAssignInterfaceScopes ;
function preAssignWithScopes ( ast , context ) {
var withStmt = ast ;
var withType = withStmt . type ;
var members = new ScopedMembers ( new DualStringHashTable ( new StringHashTable ( ) , new StringHashTable ( ) ) ) ;
var ambientMembers = new ScopedMembers ( new DualStringHashTable ( new StringHashTable ( ) , new StringHashTable ( ) ) ) ;
var withType = new Type ( ) ;
var withSymbol = new WithSymbol ( withStmt . minChar , context . typeFlow . checker . locationInfo . unitIndex , withType ) ;
withType . members = members ;
withType . ambientMembers = ambientMembers ;
withType . symbol = withSymbol ;
withType . setHasImplementation ( ) ;
withStmt . type = withType ;
var withScope = new TypeScript . SymbolScopeBuilder ( withType . members , withType . ambientMembers , null , null , context . scopeChain . scope , withType . symbol ) ;
pushAssignScope ( withScope , context , null , null , null ) ;
withType . containedScope = withScope ;
}
TypeScript . preAssignWithScopes = preAssignWithScopes ;
function preAssignFuncDeclScopes ( ast , context ) {
var funcDecl = ast ;
var container = null ;
var localContainer = null ;
if ( funcDecl . type ) {
localContainer = ast . type . symbol ;
}
var isStatic = hasFlag ( funcDecl . fncFlags , FncFlags . Static ) ;
var isInnerStatic = isStatic && context . scopeChain . fnc != null ;
// for inner static functions, use the parent's member scope, so local vars cannot be captured
var parentScope = isInnerStatic ? context.scopeChain.fnc.type.memberScope : context.scopeChain.scope ;
// if this is not a method, but enclosed by class, use constructor as
// the enclosing scope
// REVIEW: Some twisted logic here - this needs to be cleaned up once old classes are removed
// - if it's a new class, always use the contained scope, since we initialize the constructor scope below
2015-03-26 21:46:35 +01:00
if ( context . scopeChain . thisType &&
( ! funcDecl . isConstructor || hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) ) {
2015-02-03 00:30:33 +01:00
var instType = context . scopeChain . thisType ;
if ( ! ( instType . typeFlags & TypeFlags . IsClass ) && ! hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) {
if ( ! funcDecl . isMethod ( ) || isStatic ) {
parentScope = instType . constructorScope ;
}
else {
// use constructor scope if a method as well
parentScope = instType . containedScope ;
}
}
else {
2015-03-26 21:46:35 +01:00
if ( context . scopeChain . previous . scope . container &&
context . scopeChain . previous . scope . container . declAST &&
context . scopeChain . previous . scope . container . declAST . nodeType == NodeType . FuncDecl &&
context . scopeChain . previous . scope . container . declAST . isConstructor ) {
2015-02-03 00:30:33 +01:00
// if the parent is the class constructor, use the constructor scope
parentScope = instType . constructorScope ;
}
else if ( isStatic && context . scopeChain . classType ) {
parentScope = context . scopeChain . classType . containedScope ;
}
else {
// else, use the contained scope
parentScope = instType . containedScope ;
}
}
container = instType . symbol ;
}
else if ( funcDecl . isConstructor && context . scopeChain . thisType ) {
// sets the container to the class type's symbol (which is shared by the instance type)
container = context . scopeChain . thisType . symbol ;
}
if ( funcDecl . type == null || hasFlag ( funcDecl . type . symbol . flags , SymbolFlags . TypeSetDuringScopeAssignment ) ) {
if ( context . scopeChain . fnc && context . scopeChain . fnc . type ) {
container = context . scopeChain . fnc . type . symbol ;
}
var funcScope = null ;
var outerFnc = context . scopeChain . fnc ;
var nameText = funcDecl . name ? funcDecl.name.actualText : null ;
var fgSym = null ;
if ( isStatic ) {
// In the case of function-nested statics, no member list will have bee initialized for the function, so we need
// to copy it over. We don't set this by default because having a non-null member list will throw off assignment
// compatibility tests
if ( outerFnc . type . members == null && container . getType ( ) . memberScope ) {
outerFnc . type . members = container . type . memberScope . valueMembers ;
}
funcScope = context . scopeChain . fnc . type . memberScope ;
outerFnc . innerStaticFuncs [ outerFnc . innerStaticFuncs . length ] = funcDecl ;
}
else {
2015-03-26 21:46:35 +01:00
if ( ! funcDecl . isConstructor &&
container &&
container . declAST &&
container . declAST . nodeType == NodeType . FuncDecl &&
container . declAST . isConstructor &&
! funcDecl . isMethod ( ) ) {
2015-02-03 00:30:33 +01:00
funcScope = context . scopeChain . thisType . constructorScope ; //locals;
}
else {
funcScope = context . scopeChain . scope ;
}
}
// REVIEW: We don't search for another sym for accessors to prevent us from
// accidentally coalescing function signatures with the same name (E.g., a function
// 'f' the outer scope and a setter 'f' in an object literal within that scope)
if ( nameText && nameText != "__missing" && ! funcDecl . isAccessor ( ) ) {
if ( isStatic ) {
fgSym = funcScope . findLocal ( nameText , false , false ) ;
}
else {
// REVIEW: This logic should be symmetric with preCollectClassTypes
fgSym = funcScope . findLocal ( nameText , false , false ) ;
}
}
context . typeFlow . checker . createFunctionSignature ( funcDecl , container , funcScope , fgSym , fgSym == null ) ;
// it's a getter or setter for a class property
2015-03-26 21:46:35 +01:00
if ( ! funcDecl . accessorSymbol &&
( funcDecl . fncFlags & FncFlags . ClassMethod ) &&
container &&
( ( ! fgSym || fgSym . declAST . nodeType != NodeType . FuncDecl ) && funcDecl . isAccessor ( ) ) ||
( fgSym && fgSym . isAccessor ( ) ) ) {
2015-02-03 00:30:33 +01:00
funcDecl . accessorSymbol = context . typeFlow . checker . createAccessorSymbol ( funcDecl , fgSym , container . getType ( ) , ( funcDecl . isMethod ( ) && isStatic ) , true , funcScope , container ) ;
}
funcDecl . type . symbol . flags |= SymbolFlags . TypeSetDuringScopeAssignment ;
}
// Set the symbol for functions and their overloads
if ( funcDecl . name && funcDecl . type ) {
funcDecl . name . sym = funcDecl . type . symbol ;
}
// Keep track of the original scope type, because target typing might override
// the "type" member. We need the original "Scope type" for completion list, etc.
funcDecl . scopeType = funcDecl . type ;
// Overloads have no scope, so bail here
if ( funcDecl . isOverload ) {
return ;
}
var funcTable = new StringHashTable ( ) ;
var funcMembers = new ScopedMembers ( new DualStringHashTable ( funcTable , new StringHashTable ( ) ) ) ;
var ambientFuncTable = new StringHashTable ( ) ;
var ambientFuncMembers = new ScopedMembers ( new DualStringHashTable ( ambientFuncTable , new StringHashTable ( ) ) ) ;
var funcStaticTable = new StringHashTable ( ) ;
var funcStaticMembers = new ScopedMembers ( new DualStringHashTable ( funcStaticTable , new StringHashTable ( ) ) ) ;
var ambientFuncStaticTable = new StringHashTable ( ) ;
var ambientFuncStaticMembers = new ScopedMembers ( new DualStringHashTable ( ambientFuncStaticTable , new StringHashTable ( ) ) ) ;
// REVIEW: Is it a problem that this is being set twice for properties and constructors?
funcDecl . unitIndex = context . typeFlow . checker . locationInfo . unitIndex ;
var locals = new SymbolScopeBuilder ( funcMembers , ambientFuncMembers , null , null , parentScope , localContainer ) ;
var statics = new SymbolScopeBuilder ( funcStaticMembers , ambientFuncStaticMembers , null , null , parentScope , null ) ;
if ( funcDecl . isConstructor && context . scopeChain . thisType ) {
context . scopeChain . thisType . constructorScope = locals ;
}
// basically, there are two problems
// - Above, for new classes, we were overwriting the constructor scope with the containing scope. This caused constructor params to be
// in scope everywhere
// - Below, we're setting the contained scope table to the same table we were overwriting the constructor scope with, which we need to
// fish lambda params, etc, out (see funcTable below)
//
// A good first approach to solving this would be to change addLocalsFromScope to take a scope instead of a table, and add to the
// constructor scope as appropriate
funcDecl . symbols = funcTable ;
if ( ! funcDecl . isSpecialFn ( ) ) {
var group = funcDecl . type ;
var signature = funcDecl . signature ;
if ( ! funcDecl . isConstructor ) {
group . containedScope = locals ;
locals . container = group . symbol ;
group . memberScope = statics ;
statics . container = group . symbol ;
}
funcDecl . enclosingFnc = context . scopeChain . fnc ;
group . enclosingType = isStatic ? context.scopeChain.classType : context.scopeChain.thisType ;
// for mapping when type checking
var fgSym = ast . type . symbol ;
if ( ( ( funcDecl . fncFlags & FncFlags . Signature ) == FncFlags . None ) && funcDecl . vars ) {
context . typeFlow . addLocalsFromScope ( locals , fgSym , funcDecl . vars , funcTable , false ) ;
context . typeFlow . addLocalsFromScope ( statics , fgSym , funcDecl . statics , funcStaticTable , false ) ;
}
if ( signature . parameters ) {
var len = signature . parameters . length ;
for ( var i = 0 ; i < len ; i ++ ) {
var paramSym = signature . parameters [ i ] ;
context . typeFlow . checker . resolveTypeLink ( locals , paramSym . parameter . typeLink , true ) ;
}
}
context . typeFlow . checker . resolveTypeLink ( locals , signature . returnType , funcDecl . isSignature ( ) ) ;
}
if ( ! funcDecl . isConstructor || hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) {
var thisType = ( funcDecl . isConstructor && hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) ? context.scopeChain.thisType : null ;
pushAssignScope ( locals , context , thisType , null , funcDecl ) ;
}
}
TypeScript . preAssignFuncDeclScopes = preAssignFuncDeclScopes ;
function preAssignCatchScopes ( ast , context ) {
var catchBlock = ast ;
if ( catchBlock . param ) {
var catchTable = new ScopedMembers ( new DualStringHashTable ( new StringHashTable ( ) , new StringHashTable ( ) ) ) ; // REVIEW: Should we be allocating a public table instead of a private one?
var catchLocals = new SymbolScopeBuilder ( catchTable , null , null , null , context . scopeChain . scope , context . scopeChain . scope . container ) ;
catchBlock . containedScope = catchLocals ;
pushAssignScope ( catchLocals , context , context . scopeChain . thisType , context . scopeChain . classType , context . scopeChain . fnc ) ;
}
}
TypeScript . preAssignCatchScopes = preAssignCatchScopes ;
function preAssignScopes ( ast , parent , walker ) {
var context = walker . state ;
var go = true ;
if ( ast ) {
if ( ast . nodeType == NodeType . List ) {
var list = ast ;
list . enclosingScope = context . scopeChain . scope ;
}
else if ( ast . nodeType == NodeType . ModuleDeclaration ) {
preAssignModuleScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . ClassDeclaration ) {
preAssignClassScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . InterfaceDeclaration ) {
preAssignInterfaceScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . With ) {
preAssignWithScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . FuncDecl ) {
preAssignFuncDeclScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . Catch ) {
preAssignCatchScopes ( ast , context ) ;
}
else if ( ast . nodeType == NodeType . TypeRef ) {
go = false ;
}
}
walker . options . goChildren = go ;
return ast ;
}
TypeScript . preAssignScopes = preAssignScopes ;
function postAssignScopes ( ast , parent , walker ) {
var context = walker . state ;
var go = true ;
if ( ast ) {
if ( ast . nodeType == NodeType . ModuleDeclaration ) {
var prevModDecl = ast ;
popAssignScope ( context ) ;
context . modDeclChain . pop ( ) ;
if ( context . modDeclChain . length >= 1 ) {
context . typeFlow . checker . currentModDecl = context . modDeclChain [ context . modDeclChain . length - 1 ] ;
}
}
else if ( ast . nodeType == NodeType . ClassDeclaration ) {
popAssignScope ( context ) ;
}
else if ( ast . nodeType == NodeType . InterfaceDeclaration ) {
popAssignScope ( context ) ;
}
else if ( ast . nodeType == NodeType . With ) {
popAssignScope ( context ) ;
}
else if ( ast . nodeType == NodeType . FuncDecl ) {
var funcDecl = ast ;
if ( ( ! funcDecl . isConstructor || hasFlag ( funcDecl . fncFlags , FncFlags . ClassMethod ) ) && ! funcDecl . isOverload ) {
popAssignScope ( context ) ;
}
}
else if ( ast . nodeType == NodeType . Catch ) {
var catchBlock = ast ;
if ( catchBlock . param ) {
popAssignScope ( context ) ;
}
}
else {
go = false ;
}
}
walker . options . goChildren = go ;
return ast ;
}
TypeScript . postAssignScopes = postAssignScopes ;
} ) ( TypeScript || ( TypeScript = { } ) ) ;