• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//// [parserRealSource8.ts]
2// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
3// See LICENSE.txt in the project root for complete license information.
4
5///<reference path='typescript.ts' />
6
7module TypeScript {
8
9    export class AssignScopeContext {
10        constructor (public scopeChain: ScopeChain,
11                     public typeFlow: TypeFlow,
12                     public modDeclChain: ModuleDeclaration[]) {
13        }
14    }
15
16    export function pushAssignScope(scope: SymbolScope,
17        context: AssignScopeContext,
18        type: Type,
19        classType: Type,
20        fnc: FuncDecl) {
21
22        var chain = new ScopeChain(null, context.scopeChain, scope);
23        chain.thisType = type;
24        chain.classType = classType;
25        chain.fnc = fnc;
26        context.scopeChain = chain;
27    }
28
29    export function popAssignScope(context: AssignScopeContext) {
30        context.scopeChain = context.scopeChain.previous;
31    }
32
33    export function instanceCompare(a: Symbol, b: Symbol) {
34        if (((a == null) || (!a.isInstanceProperty()))) {
35            return b;
36        }
37        else {
38            return a;
39        }
40    }
41
42    export function instanceFilterStop(s: Symbol) {
43        return s.isInstanceProperty();
44    }
45
46    export class ScopeSearchFilter {
47
48        constructor (public select: (a: Symbol, b: Symbol) =>Symbol,
49                            public stop: (s: Symbol) =>boolean) { }
50
51        public result: Symbol = null;
52
53        public reset() {
54            this.result = null;
55        }
56
57        public update(b: Symbol): boolean {
58            this.result = this.select(this.result, b);
59            if (this.result) {
60                return this.stop(this.result);
61            }
62            else {
63                return false;
64            }
65        }
66    }
67
68    export var instanceFilter = new ScopeSearchFilter(instanceCompare, instanceFilterStop);
69
70    export function preAssignModuleScopes(ast: AST, context: AssignScopeContext) {
71        var moduleDecl = <ModuleDeclaration>ast;
72        var memberScope: SymbolTableScope = null;
73        var aggScope: SymbolAggregateScope = null;
74
75        if (moduleDecl.name && moduleDecl.mod) {
76            moduleDecl.name.sym = moduleDecl.mod.symbol;
77        }
78
79        var mod = moduleDecl.mod;
80
81        // We're likely here because of error recovery
82        if (!mod) {
83            return;
84        }
85
86        memberScope = new SymbolTableScope(mod.members, mod.ambientMembers, mod.enclosedTypes, mod.ambientEnclosedTypes, mod.symbol);
87        mod.memberScope = memberScope;
88        context.modDeclChain.push(moduleDecl);
89        context.typeFlow.checker.currentModDecl = moduleDecl;
90        aggScope = new SymbolAggregateScope(mod.symbol);
91        aggScope.addParentScope(memberScope);
92        aggScope.addParentScope(context.scopeChain.scope);
93        pushAssignScope(aggScope, context, null, null, null);
94        mod.containedScope = aggScope;
95        if (mod.symbol) {
96            context.typeFlow.addLocalsFromScope(mod.containedScope, mod.symbol, moduleDecl.vars, mod.members.privateMembers, true);
97        }
98    }
99
100    export function preAssignClassScopes(ast: AST, context: AssignScopeContext) {
101        var classDecl = <InterfaceDeclaration>ast;
102        var memberScope: SymbolTableScope = null;
103        var aggScope: SymbolAggregateScope = null;
104
105        if (classDecl.name && classDecl.type) {
106            classDecl.name.sym = classDecl.type.symbol;
107        }
108
109        var classType = ast.type;
110
111        if (classType) {
112            var classSym = classType.symbol;
113            memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(classType);
114
115            aggScope = new SymbolAggregateScope(classType.symbol);
116            aggScope.addParentScope(memberScope);
117            aggScope.addParentScope(context.scopeChain.scope);
118
119            classType.containedScope = aggScope;
120            classType.memberScope = memberScope;
121
122            var instanceType = classType.instanceType;
123            memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(instanceType);
124            instanceType.memberScope = memberScope;
125
126            aggScope = new SymbolAggregateScope(instanceType.symbol);
127            aggScope.addParentScope(context.scopeChain.scope);
128
129            pushAssignScope(aggScope, context, instanceType, classType, null);
130            instanceType.containedScope = aggScope;
131        }
132        else {
133            ast.type = context.typeFlow.anyType;
134        }
135    }
136
137    export function preAssignInterfaceScopes(ast: AST, context: AssignScopeContext) {
138        var interfaceDecl = <InterfaceDeclaration>ast;
139        var memberScope: SymbolTableScope = null;
140        var aggScope: SymbolAggregateScope = null;
141
142        if (interfaceDecl.name && interfaceDecl.type) {
143            interfaceDecl.name.sym = interfaceDecl.type.symbol;
144        }
145
146        var interfaceType = ast.type;
147        memberScope = <SymbolTableScope>context.typeFlow.checker.scopeOf(interfaceType);
148        interfaceType.memberScope = memberScope;
149        aggScope = new SymbolAggregateScope(interfaceType.symbol);
150        aggScope.addParentScope(memberScope);
151        aggScope.addParentScope(context.scopeChain.scope);
152        pushAssignScope(aggScope, context, null, null, null);
153        interfaceType.containedScope = aggScope;
154    }
155
156    export function preAssignWithScopes(ast: AST, context: AssignScopeContext) {
157        var withStmt = <WithStatement>ast;
158        var withType = withStmt.type;
159
160        var members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
161        var ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
162
163        var withType = new Type();
164        var withSymbol = new WithSymbol(withStmt.minChar, context.typeFlow.checker.locationInfo.unitIndex, withType);
165        withType.members = members;
166        withType.ambientMembers = ambientMembers;
167        withType.symbol = withSymbol;
168        withType.setHasImplementation();
169        withStmt.type = withType;
170
171        var withScope = new TypeScript.SymbolScopeBuilder(withType.members, withType.ambientMembers, null, null, context.scopeChain.scope, withType.symbol);
172
173        pushAssignScope(withScope, context, null, null, null);
174        withType.containedScope = withScope;
175    }
176
177    export function preAssignFuncDeclScopes(ast: AST, context: AssignScopeContext) {
178        var funcDecl = <FuncDecl>ast;
179
180        var container: Symbol = null;
181        var localContainer: Symbol = null;
182        if (funcDecl.type) {
183            localContainer = ast.type.symbol;
184        }
185
186        var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);
187        var isInnerStatic = isStatic && context.scopeChain.fnc != null;
188        // for inner static functions, use the parent's member scope, so local vars cannot be captured
189        var parentScope = isInnerStatic ? context.scopeChain.fnc.type.memberScope : context.scopeChain.scope;
190
191        // if this is not a method, but enclosed by class, use constructor as
192        // the enclosing scope
193        // REVIEW: Some twisted logic here - this needs to be cleaned up once old classes are removed
194        //  - if it's a new class, always use the contained scope, since we initialize the constructor scope below
195        if (context.scopeChain.thisType &&
196            (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod))) {
197            var instType = context.scopeChain.thisType;
198
199            if (!(instType.typeFlags & TypeFlags.IsClass) && !hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {
200                if (!funcDecl.isMethod() || isStatic) {
201                    parentScope = instType.constructorScope;
202                }
203                else {
204                    // use constructor scope if a method as well
205                    parentScope = instType.containedScope;
206                }
207            }
208            else {
209                if (context.scopeChain.previous.scope.container &&
210                    context.scopeChain.previous.scope.container.declAST &&
211                    context.scopeChain.previous.scope.container.declAST.nodeType == NodeType.FuncDecl &&
212                    (<FuncDecl>context.scopeChain.previous.scope.container.declAST).isConstructor) {
213
214                        // if the parent is the class constructor, use the constructor scope
215                    parentScope = instType.constructorScope;
216                }
217                else if (isStatic && context.scopeChain.classType) {
218                    parentScope = context.scopeChain.classType.containedScope;
219                }
220                else {
221                    // else, use the contained scope
222                    parentScope = instType.containedScope;
223                }
224            }
225            container = instType.symbol;
226        }
227        else if (funcDecl.isConstructor && context.scopeChain.thisType) {
228            // sets the container to the class type's symbol (which is shared by the instance type)
229            container = context.scopeChain.thisType.symbol;
230        }
231
232        if (funcDecl.type == null || hasFlag(funcDecl.type.symbol.flags, SymbolFlags.TypeSetDuringScopeAssignment)) {
233            if (context.scopeChain.fnc && context.scopeChain.fnc.type) {
234                container = context.scopeChain.fnc.type.symbol;
235            }
236
237            var funcScope = null;
238            var outerFnc: FuncDecl = context.scopeChain.fnc;
239            var nameText = funcDecl.name ? funcDecl.name.actualText : null;
240            var fgSym: TypeSymbol = null;
241
242            if (isStatic) {
243                // In the case of function-nested statics, no member list will have bee initialized for the function, so we need
244                // to copy it over.  We don't set this by default because having a non-null member list will throw off assignment
245                // compatibility tests
246                if (outerFnc.type.members == null && container.getType().memberScope) {
247                    outerFnc.type.members = (<SymbolScopeBuilder>(<TypeSymbol>container).type.memberScope).valueMembers;
248                }
249                funcScope = context.scopeChain.fnc.type.memberScope;
250                outerFnc.innerStaticFuncs[outerFnc.innerStaticFuncs.length] = funcDecl;
251            }
252            else {
253
254                if (!funcDecl.isConstructor &&
255                    container &&
256                    container.declAST &&
257                    container.declAST.nodeType == NodeType.FuncDecl &&
258                    (<FuncDecl>container.declAST).isConstructor &&
259                    !funcDecl.isMethod()) {
260                    funcScope = context.scopeChain.thisType.constructorScope;//locals;
261                }
262                else {
263                    funcScope = context.scopeChain.scope;
264                }
265            }
266
267            // REVIEW: We don't search for another sym for accessors to prevent us from
268            // accidentally coalescing function signatures with the same name (E.g., a function
269            // 'f' the outer scope and a setter 'f' in an object literal within that scope)
270            if (nameText && nameText != "__missing" && !funcDecl.isAccessor()) {
271                if (isStatic) {
272                    fgSym = funcScope.findLocal(nameText, false, false);
273                }
274                else {
275                    // REVIEW: This logic should be symmetric with preCollectClassTypes
276                    fgSym = funcScope.findLocal(nameText, false, false);
277                }
278            }
279
280            context.typeFlow.checker.createFunctionSignature(funcDecl, container,
281                                                            funcScope, fgSym, fgSym == null);
282
283            // it's a getter or setter for a class property
284            if (!funcDecl.accessorSymbol &&
285                (funcDecl.fncFlags & FncFlags.ClassMethod) &&
286                container &&
287                ((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) ||
288                    (fgSym && fgSym.isAccessor()))
289            {
290                funcDecl.accessorSymbol = context.typeFlow.checker.createAccessorSymbol(funcDecl, fgSym, container.getType(), (funcDecl.isMethod() && isStatic), true, funcScope, container);
291            }
292
293            funcDecl.type.symbol.flags |= SymbolFlags.TypeSetDuringScopeAssignment;
294        }
295
296        // Set the symbol for functions and their overloads
297        if (funcDecl.name && funcDecl.type) {
298            funcDecl.name.sym = funcDecl.type.symbol;
299        }
300
301        // Keep track of the original scope type, because target typing might override
302        // the "type" member. We need the original "Scope type" for completion list, etc.
303        funcDecl.scopeType = funcDecl.type;
304
305        // Overloads have no scope, so bail here
306        if (funcDecl.isOverload) {
307            return;
308        }
309
310        var funcTable = new StringHashTable();
311        var funcMembers = new ScopedMembers(new DualStringHashTable(funcTable, new StringHashTable()));
312        var ambientFuncTable = new StringHashTable();
313        var ambientFuncMembers = new ScopedMembers(new DualStringHashTable(ambientFuncTable, new StringHashTable()));
314        var funcStaticTable = new StringHashTable();
315        var funcStaticMembers = new ScopedMembers(new DualStringHashTable(funcStaticTable, new StringHashTable()));
316        var ambientFuncStaticTable = new StringHashTable();
317        var ambientFuncStaticMembers = new ScopedMembers(new DualStringHashTable(ambientFuncStaticTable, new StringHashTable()));
318
319        // REVIEW: Is it a problem that this is being set twice for properties and constructors?
320        funcDecl.unitIndex = context.typeFlow.checker.locationInfo.unitIndex;
321
322        var locals = new SymbolScopeBuilder(funcMembers, ambientFuncMembers, null, null, parentScope, localContainer);
323        var statics = new SymbolScopeBuilder(funcStaticMembers, ambientFuncStaticMembers, null, null, parentScope, null);
324
325        if (funcDecl.isConstructor && context.scopeChain.thisType) {
326            context.scopeChain.thisType.constructorScope = locals;
327        }
328
329        // basically, there are two problems
330        // - Above, for new classes, we were overwriting the constructor scope with the containing scope.  This caused constructor params to be
331        // in scope everywhere
332        // - Below, we're setting the contained scope table to the same table we were overwriting the constructor scope with, which we need to
333        // fish lambda params, etc, out (see funcTable below)
334        //
335        // A good first approach to solving this would be to change addLocalsFromScope to take a scope instead of a table, and add to the
336        // constructor scope as appropriate
337
338        funcDecl.symbols = funcTable;
339
340        if (!funcDecl.isSpecialFn()) {
341            var group = funcDecl.type;
342            var signature = funcDecl.signature;
343
344            if (!funcDecl.isConstructor) {
345                group.containedScope = locals;
346                locals.container = group.symbol;
347
348                group.memberScope = statics;
349                statics.container = group.symbol;
350            }
351            funcDecl.enclosingFnc = context.scopeChain.fnc;
352            group.enclosingType = isStatic ? context.scopeChain.classType : context.scopeChain.thisType;
353            // for mapping when type checking
354            var fgSym = <TypeSymbol>ast.type.symbol;
355            if (((funcDecl.fncFlags & FncFlags.Signature) == FncFlags.None) && funcDecl.vars) {
356                context.typeFlow.addLocalsFromScope(locals, fgSym, funcDecl.vars,
357                                                    funcTable, false);
358                context.typeFlow.addLocalsFromScope(statics, fgSym, funcDecl.statics,
359                                                    funcStaticTable, false);
360            }
361            if (signature.parameters) {
362                var len = signature.parameters.length;
363                for (var i = 0; i < len; i++) {
364                    var paramSym: ParameterSymbol = signature.parameters[i];
365                    context.typeFlow.checker.resolveTypeLink(locals,
366                                                                paramSym.parameter.typeLink, true);
367                }
368            }
369            context.typeFlow.checker.resolveTypeLink(locals, signature.returnType,
370                                                        funcDecl.isSignature());
371        }
372
373        if (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {
374            var thisType = (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) ? context.scopeChain.thisType : null;
375            pushAssignScope(locals, context, thisType, null, funcDecl);
376        }
377    }
378
379    export function preAssignCatchScopes(ast: AST, context: AssignScopeContext) {
380        var catchBlock = <Catch>ast;
381        if (catchBlock.param) {
382            var catchTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable())); // REVIEW: Should we be allocating a public table instead of a private one?
383            var catchLocals = new SymbolScopeBuilder(catchTable, null, null, null, context.scopeChain.scope,
384                                                   context.scopeChain.scope.container);
385            catchBlock.containedScope = catchLocals;
386            pushAssignScope(catchLocals, context, context.scopeChain.thisType, context.scopeChain.classType, context.scopeChain.fnc);
387        }
388    }
389
390    export function preAssignScopes(ast: AST, parent: AST, walker: IAstWalker) {
391        var context:AssignScopeContext = walker.state;
392        var go = true;
393
394        if (ast) {
395            if (ast.nodeType == NodeType.List) {
396                var list = <ASTList>ast;
397                list.enclosingScope = context.scopeChain.scope;
398            }
399            else if (ast.nodeType == NodeType.ModuleDeclaration) {
400                preAssignModuleScopes(ast, context);
401            }
402            else if (ast.nodeType == NodeType.ClassDeclaration) {
403                preAssignClassScopes(ast, context);
404            }
405            else if (ast.nodeType == NodeType.InterfaceDeclaration) {
406                preAssignInterfaceScopes(ast, context);
407            }
408            else if (ast.nodeType == NodeType.With) {
409                preAssignWithScopes(ast, context);
410            }
411            else if (ast.nodeType == NodeType.FuncDecl) {
412                preAssignFuncDeclScopes(ast, context);
413            }
414            else if (ast.nodeType == NodeType.Catch) {
415                preAssignCatchScopes(ast, context);
416            }
417            else if (ast.nodeType == NodeType.TypeRef) {
418                go = false;
419            }
420        }
421        walker.options.goChildren = go;
422        return ast;
423    }
424
425    export function postAssignScopes(ast: AST, parent: AST, walker: IAstWalker) {
426        var context:AssignScopeContext = walker.state;
427        var go = true;
428        if (ast) {
429            if (ast.nodeType == NodeType.ModuleDeclaration) {
430                var prevModDecl = <ModuleDeclaration>ast;
431
432                popAssignScope(context);
433
434                context.modDeclChain.pop();
435                if (context.modDeclChain.length >= 1) {
436                    context.typeFlow.checker.currentModDecl = context.modDeclChain[context.modDeclChain.length - 1];
437                }
438            }
439            else if (ast.nodeType == NodeType.ClassDeclaration) {
440                popAssignScope(context);
441            }
442            else if (ast.nodeType == NodeType.InterfaceDeclaration) {
443                popAssignScope(context);
444            }
445            else if (ast.nodeType == NodeType.With) {
446                popAssignScope(context);
447            }
448            else if (ast.nodeType == NodeType.FuncDecl) {
449                var funcDecl = <FuncDecl>ast;
450                if ((!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) && !funcDecl.isOverload) {
451                    popAssignScope(context);
452                }
453            }
454            else if (ast.nodeType == NodeType.Catch) {
455                var catchBlock = <Catch>ast;
456                if (catchBlock.param) {
457                    popAssignScope(context);
458                }
459            }
460            else {
461                go = false;
462            }
463        }
464        walker.options.goChildren = go;
465        return ast;
466    }
467}
468
469//// [parserRealSource8.js]
470// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
471// See LICENSE.txt in the project root for complete license information.
472///<reference path='typescript.ts' />
473var TypeScript;
474(function (TypeScript) {
475    var AssignScopeContext = /** @class */ (function () {
476        function AssignScopeContext(scopeChain, typeFlow, modDeclChain) {
477            this.scopeChain = scopeChain;
478            this.typeFlow = typeFlow;
479            this.modDeclChain = modDeclChain;
480        }
481        return AssignScopeContext;
482    }());
483    TypeScript.AssignScopeContext = AssignScopeContext;
484    function pushAssignScope(scope, context, type, classType, fnc) {
485        var chain = new ScopeChain(null, context.scopeChain, scope);
486        chain.thisType = type;
487        chain.classType = classType;
488        chain.fnc = fnc;
489        context.scopeChain = chain;
490    }
491    TypeScript.pushAssignScope = pushAssignScope;
492    function popAssignScope(context) {
493        context.scopeChain = context.scopeChain.previous;
494    }
495    TypeScript.popAssignScope = popAssignScope;
496    function instanceCompare(a, b) {
497        if (((a == null) || (!a.isInstanceProperty()))) {
498            return b;
499        }
500        else {
501            return a;
502        }
503    }
504    TypeScript.instanceCompare = instanceCompare;
505    function instanceFilterStop(s) {
506        return s.isInstanceProperty();
507    }
508    TypeScript.instanceFilterStop = instanceFilterStop;
509    var ScopeSearchFilter = /** @class */ (function () {
510        function ScopeSearchFilter(select, stop) {
511            this.select = select;
512            this.stop = stop;
513            this.result = null;
514        }
515        ScopeSearchFilter.prototype.reset = function () {
516            this.result = null;
517        };
518        ScopeSearchFilter.prototype.update = function (b) {
519            this.result = this.select(this.result, b);
520            if (this.result) {
521                return this.stop(this.result);
522            }
523            else {
524                return false;
525            }
526        };
527        return ScopeSearchFilter;
528    }());
529    TypeScript.ScopeSearchFilter = ScopeSearchFilter;
530    TypeScript.instanceFilter = new ScopeSearchFilter(instanceCompare, instanceFilterStop);
531    function preAssignModuleScopes(ast, context) {
532        var moduleDecl = ast;
533        var memberScope = null;
534        var aggScope = null;
535        if (moduleDecl.name && moduleDecl.mod) {
536            moduleDecl.name.sym = moduleDecl.mod.symbol;
537        }
538        var mod = moduleDecl.mod;
539        // We're likely here because of error recovery
540        if (!mod) {
541            return;
542        }
543        memberScope = new SymbolTableScope(mod.members, mod.ambientMembers, mod.enclosedTypes, mod.ambientEnclosedTypes, mod.symbol);
544        mod.memberScope = memberScope;
545        context.modDeclChain.push(moduleDecl);
546        context.typeFlow.checker.currentModDecl = moduleDecl;
547        aggScope = new SymbolAggregateScope(mod.symbol);
548        aggScope.addParentScope(memberScope);
549        aggScope.addParentScope(context.scopeChain.scope);
550        pushAssignScope(aggScope, context, null, null, null);
551        mod.containedScope = aggScope;
552        if (mod.symbol) {
553            context.typeFlow.addLocalsFromScope(mod.containedScope, mod.symbol, moduleDecl.vars, mod.members.privateMembers, true);
554        }
555    }
556    TypeScript.preAssignModuleScopes = preAssignModuleScopes;
557    function preAssignClassScopes(ast, context) {
558        var classDecl = ast;
559        var memberScope = null;
560        var aggScope = null;
561        if (classDecl.name && classDecl.type) {
562            classDecl.name.sym = classDecl.type.symbol;
563        }
564        var classType = ast.type;
565        if (classType) {
566            var classSym = classType.symbol;
567            memberScope = context.typeFlow.checker.scopeOf(classType);
568            aggScope = new SymbolAggregateScope(classType.symbol);
569            aggScope.addParentScope(memberScope);
570            aggScope.addParentScope(context.scopeChain.scope);
571            classType.containedScope = aggScope;
572            classType.memberScope = memberScope;
573            var instanceType = classType.instanceType;
574            memberScope = context.typeFlow.checker.scopeOf(instanceType);
575            instanceType.memberScope = memberScope;
576            aggScope = new SymbolAggregateScope(instanceType.symbol);
577            aggScope.addParentScope(context.scopeChain.scope);
578            pushAssignScope(aggScope, context, instanceType, classType, null);
579            instanceType.containedScope = aggScope;
580        }
581        else {
582            ast.type = context.typeFlow.anyType;
583        }
584    }
585    TypeScript.preAssignClassScopes = preAssignClassScopes;
586    function preAssignInterfaceScopes(ast, context) {
587        var interfaceDecl = ast;
588        var memberScope = null;
589        var aggScope = null;
590        if (interfaceDecl.name && interfaceDecl.type) {
591            interfaceDecl.name.sym = interfaceDecl.type.symbol;
592        }
593        var interfaceType = ast.type;
594        memberScope = context.typeFlow.checker.scopeOf(interfaceType);
595        interfaceType.memberScope = memberScope;
596        aggScope = new SymbolAggregateScope(interfaceType.symbol);
597        aggScope.addParentScope(memberScope);
598        aggScope.addParentScope(context.scopeChain.scope);
599        pushAssignScope(aggScope, context, null, null, null);
600        interfaceType.containedScope = aggScope;
601    }
602    TypeScript.preAssignInterfaceScopes = preAssignInterfaceScopes;
603    function preAssignWithScopes(ast, context) {
604        var withStmt = ast;
605        var withType = withStmt.type;
606        var members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
607        var ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
608        var withType = new Type();
609        var withSymbol = new WithSymbol(withStmt.minChar, context.typeFlow.checker.locationInfo.unitIndex, withType);
610        withType.members = members;
611        withType.ambientMembers = ambientMembers;
612        withType.symbol = withSymbol;
613        withType.setHasImplementation();
614        withStmt.type = withType;
615        var withScope = new TypeScript.SymbolScopeBuilder(withType.members, withType.ambientMembers, null, null, context.scopeChain.scope, withType.symbol);
616        pushAssignScope(withScope, context, null, null, null);
617        withType.containedScope = withScope;
618    }
619    TypeScript.preAssignWithScopes = preAssignWithScopes;
620    function preAssignFuncDeclScopes(ast, context) {
621        var funcDecl = ast;
622        var container = null;
623        var localContainer = null;
624        if (funcDecl.type) {
625            localContainer = ast.type.symbol;
626        }
627        var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);
628        var isInnerStatic = isStatic && context.scopeChain.fnc != null;
629        // for inner static functions, use the parent's member scope, so local vars cannot be captured
630        var parentScope = isInnerStatic ? context.scopeChain.fnc.type.memberScope : context.scopeChain.scope;
631        // if this is not a method, but enclosed by class, use constructor as
632        // the enclosing scope
633        // REVIEW: Some twisted logic here - this needs to be cleaned up once old classes are removed
634        //  - if it's a new class, always use the contained scope, since we initialize the constructor scope below
635        if (context.scopeChain.thisType &&
636            (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod))) {
637            var instType = context.scopeChain.thisType;
638            if (!(instType.typeFlags & TypeFlags.IsClass) && !hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {
639                if (!funcDecl.isMethod() || isStatic) {
640                    parentScope = instType.constructorScope;
641                }
642                else {
643                    // use constructor scope if a method as well
644                    parentScope = instType.containedScope;
645                }
646            }
647            else {
648                if (context.scopeChain.previous.scope.container &&
649                    context.scopeChain.previous.scope.container.declAST &&
650                    context.scopeChain.previous.scope.container.declAST.nodeType == NodeType.FuncDecl &&
651                    context.scopeChain.previous.scope.container.declAST.isConstructor) {
652                    // if the parent is the class constructor, use the constructor scope
653                    parentScope = instType.constructorScope;
654                }
655                else if (isStatic && context.scopeChain.classType) {
656                    parentScope = context.scopeChain.classType.containedScope;
657                }
658                else {
659                    // else, use the contained scope
660                    parentScope = instType.containedScope;
661                }
662            }
663            container = instType.symbol;
664        }
665        else if (funcDecl.isConstructor && context.scopeChain.thisType) {
666            // sets the container to the class type's symbol (which is shared by the instance type)
667            container = context.scopeChain.thisType.symbol;
668        }
669        if (funcDecl.type == null || hasFlag(funcDecl.type.symbol.flags, SymbolFlags.TypeSetDuringScopeAssignment)) {
670            if (context.scopeChain.fnc && context.scopeChain.fnc.type) {
671                container = context.scopeChain.fnc.type.symbol;
672            }
673            var funcScope = null;
674            var outerFnc = context.scopeChain.fnc;
675            var nameText = funcDecl.name ? funcDecl.name.actualText : null;
676            var fgSym = null;
677            if (isStatic) {
678                // In the case of function-nested statics, no member list will have bee initialized for the function, so we need
679                // to copy it over.  We don't set this by default because having a non-null member list will throw off assignment
680                // compatibility tests
681                if (outerFnc.type.members == null && container.getType().memberScope) {
682                    outerFnc.type.members = container.type.memberScope.valueMembers;
683                }
684                funcScope = context.scopeChain.fnc.type.memberScope;
685                outerFnc.innerStaticFuncs[outerFnc.innerStaticFuncs.length] = funcDecl;
686            }
687            else {
688                if (!funcDecl.isConstructor &&
689                    container &&
690                    container.declAST &&
691                    container.declAST.nodeType == NodeType.FuncDecl &&
692                    container.declAST.isConstructor &&
693                    !funcDecl.isMethod()) {
694                    funcScope = context.scopeChain.thisType.constructorScope; //locals;
695                }
696                else {
697                    funcScope = context.scopeChain.scope;
698                }
699            }
700            // REVIEW: We don't search for another sym for accessors to prevent us from
701            // accidentally coalescing function signatures with the same name (E.g., a function
702            // 'f' the outer scope and a setter 'f' in an object literal within that scope)
703            if (nameText && nameText != "__missing" && !funcDecl.isAccessor()) {
704                if (isStatic) {
705                    fgSym = funcScope.findLocal(nameText, false, false);
706                }
707                else {
708                    // REVIEW: This logic should be symmetric with preCollectClassTypes
709                    fgSym = funcScope.findLocal(nameText, false, false);
710                }
711            }
712            context.typeFlow.checker.createFunctionSignature(funcDecl, container, funcScope, fgSym, fgSym == null);
713            // it's a getter or setter for a class property
714            if (!funcDecl.accessorSymbol &&
715                (funcDecl.fncFlags & FncFlags.ClassMethod) &&
716                container &&
717                ((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) ||
718                (fgSym && fgSym.isAccessor())) {
719                funcDecl.accessorSymbol = context.typeFlow.checker.createAccessorSymbol(funcDecl, fgSym, container.getType(), (funcDecl.isMethod() && isStatic), true, funcScope, container);
720            }
721            funcDecl.type.symbol.flags |= SymbolFlags.TypeSetDuringScopeAssignment;
722        }
723        // Set the symbol for functions and their overloads
724        if (funcDecl.name && funcDecl.type) {
725            funcDecl.name.sym = funcDecl.type.symbol;
726        }
727        // Keep track of the original scope type, because target typing might override
728        // the "type" member. We need the original "Scope type" for completion list, etc.
729        funcDecl.scopeType = funcDecl.type;
730        // Overloads have no scope, so bail here
731        if (funcDecl.isOverload) {
732            return;
733        }
734        var funcTable = new StringHashTable();
735        var funcMembers = new ScopedMembers(new DualStringHashTable(funcTable, new StringHashTable()));
736        var ambientFuncTable = new StringHashTable();
737        var ambientFuncMembers = new ScopedMembers(new DualStringHashTable(ambientFuncTable, new StringHashTable()));
738        var funcStaticTable = new StringHashTable();
739        var funcStaticMembers = new ScopedMembers(new DualStringHashTable(funcStaticTable, new StringHashTable()));
740        var ambientFuncStaticTable = new StringHashTable();
741        var ambientFuncStaticMembers = new ScopedMembers(new DualStringHashTable(ambientFuncStaticTable, new StringHashTable()));
742        // REVIEW: Is it a problem that this is being set twice for properties and constructors?
743        funcDecl.unitIndex = context.typeFlow.checker.locationInfo.unitIndex;
744        var locals = new SymbolScopeBuilder(funcMembers, ambientFuncMembers, null, null, parentScope, localContainer);
745        var statics = new SymbolScopeBuilder(funcStaticMembers, ambientFuncStaticMembers, null, null, parentScope, null);
746        if (funcDecl.isConstructor && context.scopeChain.thisType) {
747            context.scopeChain.thisType.constructorScope = locals;
748        }
749        // basically, there are two problems
750        // - Above, for new classes, we were overwriting the constructor scope with the containing scope.  This caused constructor params to be
751        // in scope everywhere
752        // - Below, we're setting the contained scope table to the same table we were overwriting the constructor scope with, which we need to
753        // fish lambda params, etc, out (see funcTable below)
754        //
755        // A good first approach to solving this would be to change addLocalsFromScope to take a scope instead of a table, and add to the
756        // constructor scope as appropriate
757        funcDecl.symbols = funcTable;
758        if (!funcDecl.isSpecialFn()) {
759            var group = funcDecl.type;
760            var signature = funcDecl.signature;
761            if (!funcDecl.isConstructor) {
762                group.containedScope = locals;
763                locals.container = group.symbol;
764                group.memberScope = statics;
765                statics.container = group.symbol;
766            }
767            funcDecl.enclosingFnc = context.scopeChain.fnc;
768            group.enclosingType = isStatic ? context.scopeChain.classType : context.scopeChain.thisType;
769            // for mapping when type checking
770            var fgSym = ast.type.symbol;
771            if (((funcDecl.fncFlags & FncFlags.Signature) == FncFlags.None) && funcDecl.vars) {
772                context.typeFlow.addLocalsFromScope(locals, fgSym, funcDecl.vars, funcTable, false);
773                context.typeFlow.addLocalsFromScope(statics, fgSym, funcDecl.statics, funcStaticTable, false);
774            }
775            if (signature.parameters) {
776                var len = signature.parameters.length;
777                for (var i = 0; i < len; i++) {
778                    var paramSym = signature.parameters[i];
779                    context.typeFlow.checker.resolveTypeLink(locals, paramSym.parameter.typeLink, true);
780                }
781            }
782            context.typeFlow.checker.resolveTypeLink(locals, signature.returnType, funcDecl.isSignature());
783        }
784        if (!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {
785            var thisType = (funcDecl.isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) ? context.scopeChain.thisType : null;
786            pushAssignScope(locals, context, thisType, null, funcDecl);
787        }
788    }
789    TypeScript.preAssignFuncDeclScopes = preAssignFuncDeclScopes;
790    function preAssignCatchScopes(ast, context) {
791        var catchBlock = ast;
792        if (catchBlock.param) {
793            var catchTable = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable())); // REVIEW: Should we be allocating a public table instead of a private one?
794            var catchLocals = new SymbolScopeBuilder(catchTable, null, null, null, context.scopeChain.scope, context.scopeChain.scope.container);
795            catchBlock.containedScope = catchLocals;
796            pushAssignScope(catchLocals, context, context.scopeChain.thisType, context.scopeChain.classType, context.scopeChain.fnc);
797        }
798    }
799    TypeScript.preAssignCatchScopes = preAssignCatchScopes;
800    function preAssignScopes(ast, parent, walker) {
801        var context = walker.state;
802        var go = true;
803        if (ast) {
804            if (ast.nodeType == NodeType.List) {
805                var list = ast;
806                list.enclosingScope = context.scopeChain.scope;
807            }
808            else if (ast.nodeType == NodeType.ModuleDeclaration) {
809                preAssignModuleScopes(ast, context);
810            }
811            else if (ast.nodeType == NodeType.ClassDeclaration) {
812                preAssignClassScopes(ast, context);
813            }
814            else if (ast.nodeType == NodeType.InterfaceDeclaration) {
815                preAssignInterfaceScopes(ast, context);
816            }
817            else if (ast.nodeType == NodeType.With) {
818                preAssignWithScopes(ast, context);
819            }
820            else if (ast.nodeType == NodeType.FuncDecl) {
821                preAssignFuncDeclScopes(ast, context);
822            }
823            else if (ast.nodeType == NodeType.Catch) {
824                preAssignCatchScopes(ast, context);
825            }
826            else if (ast.nodeType == NodeType.TypeRef) {
827                go = false;
828            }
829        }
830        walker.options.goChildren = go;
831        return ast;
832    }
833    TypeScript.preAssignScopes = preAssignScopes;
834    function postAssignScopes(ast, parent, walker) {
835        var context = walker.state;
836        var go = true;
837        if (ast) {
838            if (ast.nodeType == NodeType.ModuleDeclaration) {
839                var prevModDecl = ast;
840                popAssignScope(context);
841                context.modDeclChain.pop();
842                if (context.modDeclChain.length >= 1) {
843                    context.typeFlow.checker.currentModDecl = context.modDeclChain[context.modDeclChain.length - 1];
844                }
845            }
846            else if (ast.nodeType == NodeType.ClassDeclaration) {
847                popAssignScope(context);
848            }
849            else if (ast.nodeType == NodeType.InterfaceDeclaration) {
850                popAssignScope(context);
851            }
852            else if (ast.nodeType == NodeType.With) {
853                popAssignScope(context);
854            }
855            else if (ast.nodeType == NodeType.FuncDecl) {
856                var funcDecl = ast;
857                if ((!funcDecl.isConstructor || hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) && !funcDecl.isOverload) {
858                    popAssignScope(context);
859                }
860            }
861            else if (ast.nodeType == NodeType.Catch) {
862                var catchBlock = ast;
863                if (catchBlock.param) {
864                    popAssignScope(context);
865                }
866            }
867            else {
868                go = false;
869            }
870        }
871        walker.options.goChildren = go;
872        return ast;
873    }
874    TypeScript.postAssignScopes = postAssignScopes;
875})(TypeScript || (TypeScript = {}));
876