• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//// [parserRealSource7.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    export class Continuation {
9        public exceptionBlock = -1;
10        constructor (public normalBlock: number) { }
11    }
12
13    function getBaseTypeLinks(bases: ASTList, baseTypeLinks: TypeLink[]) {
14        if (bases) {
15            var len = bases.members.length;
16            if (baseTypeLinks == null) {
17                baseTypeLinks = new TypeLink[];
18            }
19            for (var i = 0; i < len; i++) {
20                var baseExpr = bases.members[i];
21                var name = baseExpr;
22                var typeLink = new TypeLink();
23                typeLink.ast = name;
24                baseTypeLinks[baseTypeLinks.length] = typeLink;
25            }
26        }
27        return baseTypeLinks;
28    }
29
30    function getBases(type: Type, typeDecl: TypeDeclaration) {
31        type.extendsTypeLinks = getBaseTypeLinks(typeDecl.extendsList, type.extendsTypeLinks);
32        type.implementsTypeLinks = getBaseTypeLinks(typeDecl.implementsList, type.implementsTypeLinks);
33    }
34
35    function addPrototypeField(classType: Type, ast: AST, context: TypeCollectionContext) {
36        var field = new ValueLocation();
37        field.typeLink = new TypeLink();
38        field.typeLink.ast = ast;
39        field.typeLink.type = classType.instanceType;
40
41        var fieldSymbol =
42            new FieldSymbol("prototype", ast.minChar,
43                            context.checker.locationInfo.unitIndex, true, field);
44        fieldSymbol.flags |= (SymbolFlags.Property | SymbolFlags.BuiltIn);
45        field.symbol = fieldSymbol;
46        fieldSymbol.declAST = ast;
47        classType.members.addPublicMember("prototype", fieldSymbol);
48    }
49
50    export function createNewConstructGroupForType(type: Type) {
51        var signature = new Signature();
52        signature.returnType = new TypeLink();
53        signature.returnType.type = type.instanceType;
54        signature.parameters = [];
55
56        type.construct = new SignatureGroup();
57        type.construct.addSignature(signature);
58    }
59
60    export function cloneParentConstructGroupForChildType(child: Type, parent: Type) {
61        child.construct = new SignatureGroup();
62        var sig: Signature = null;
63
64        if (!parent.construct) {
65            createNewConstructGroupForType(parent);
66        }
67
68        for (var i = 0; i < parent.construct.signatures.length; i++) {
69            sig = new Signature();
70            sig.parameters = parent.construct.signatures[i].parameters;
71            sig.nonOptionalParameterCount = parent.construct.signatures[i].nonOptionalParameterCount;
72            sig.typeCheckStatus = parent.construct.signatures[i].typeCheckStatus;
73            sig.declAST = parent.construct.signatures[i].declAST;
74            sig.returnType = new TypeLink();
75            sig.returnType.type = child.instanceType;
76            child.construct.addSignature(sig);
77        }
78
79    }
80
81    export var globalId = "__GLO";
82
83    export interface IAliasScopeContext {
84        topLevelScope: ScopeChain;
85        members: IHashTable;
86        tcContext: TypeCollectionContext;
87    }
88
89    function findTypeSymbolInScopeChain(name: string, scopeChain: ScopeChain): Symbol {
90        var symbol = scopeChain.scope.find(name, false, true);
91
92        if (symbol == null && scopeChain.previous) {
93            symbol = findTypeSymbolInScopeChain(name, scopeChain.previous);
94        }
95
96        return symbol;
97    }
98
99    function findSymbolFromAlias(alias: AST, context: IAliasScopeContext): Symbol {
100        var symbol: Symbol = null;
101        switch (alias.nodeType) {
102            case NodeType.Name:
103                var name = (<Identifier>alias).text;
104                var isDynamic = isQuoted(name);
105
106                var findSym = (id: string) => {
107                    if (context.members) {
108                        return context.members.lookup(name);
109                    }
110                    else {
111                        return findTypeSymbolInScopeChain(name, context.topLevelScope);
112                    }
113                }
114
115                if (isDynamic) {
116                    symbol = context.tcContext.checker.findSymbolForDynamicModule(name, context.tcContext.script.locationInfo.filename, findSym);
117                }
118                else {
119                    symbol = findSym(name);
120                }
121
122                break;
123
124            case NodeType.Dot:
125                var dottedExpr = <BinaryExpression>alias;
126                var op1Sym = findSymbolFromAlias(dottedExpr.operand1, context);
127
128                if (op1Sym && op1Sym.getType()) {
129                    symbol = findSymbolFromAlias(dottedExpr.operand2, context);
130                }
131
132                break;
133
134            default:
135                break;
136        }
137
138        if (symbol) {
139            var symType = symbol.getType();
140            if (symType) {
141                var members = symType.members;
142                if (members) {
143                    context.members = members.publicMembers;
144                }
145            }
146        }
147
148        return symbol;
149    }
150
151    export function preCollectImportTypes(ast: AST, parent: AST, context: TypeCollectionContext) {
152        var scopeChain = context.scopeChain;
153        var typeSymbol: TypeSymbol = null;
154        var modType: ModuleType = null;
155        var importDecl = <ImportDeclaration>ast;
156        var isExported = hasFlag(importDecl.varFlags, VarFlags.Exported);
157
158        // REVIEW: technically, this call isn't strictly necessary, since we'll find the type during the call to resolveTypeMembers
159        var aliasedModSymbol = findSymbolFromAlias(importDecl.alias, { topLevelScope: scopeChain, members: null, tcContext: context });
160        var isGlobal = context.scopeChain.container == context.checker.gloMod;
161
162        if (aliasedModSymbol) {
163            var aliasedModType = aliasedModSymbol.getType();
164
165            if (aliasedModType) {
166                modType = <ModuleType>aliasedModType;
167            }
168        }
169
170        typeSymbol = new TypeSymbol(importDecl.id.text, importDecl.minChar,
171                                    context.checker.locationInfo.unitIndex, modType);
172
173        typeSymbol.aliasLink = importDecl;
174
175        if (context.scopeChain.moduleDecl) {
176            typeSymbol.declModule = context.scopeChain.moduleDecl;
177        }
178        typeSymbol.declAST = importDecl;
179        importDecl.id.sym = typeSymbol;
180        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,
181                                context.checker.errorReporter, isExported || isGlobal, true, false);
182        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,
183                                context.checker.errorReporter, isExported || isGlobal, false, false);
184        return true;
185    }
186
187    export function preCollectModuleTypes(ast: AST, parent: AST, context: TypeCollectionContext) {
188        var scopeChain = context.scopeChain;
189
190        var moduleDecl: ModuleDeclaration = <ModuleDeclaration>ast;
191
192        var isAmbient = hasFlag(moduleDecl.modFlags, ModuleFlags.Ambient);
193        var isEnum = hasFlag(moduleDecl.modFlags, ModuleFlags.IsEnum);
194        var isGlobal = context.scopeChain.container == context.checker.gloMod;
195        var isExported = hasFlag(moduleDecl.modFlags, ModuleFlags.Exported);
196        var modName = (<Identifier>moduleDecl.name).text;
197
198        var isDynamic = isQuoted(modName);
199
200        var symbol = scopeChain.scope.findLocal(modName, false, false);
201        var typeSymbol: TypeSymbol = null;
202        var modType: ModuleType = null;
203        if ((symbol == null) || (symbol.kind() != SymbolKind.Type)) {
204
205            if (modType == null) {
206                var enclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
207                var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
208                modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);
209                if (isEnum) {
210                    modType.typeFlags |= TypeFlags.IsEnum;
211                }
212                modType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
213                modType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
214                modType.setHasImplementation();
215            }
216
217            typeSymbol = new TypeSymbol(modName, moduleDecl.minChar,
218                                        context.checker.locationInfo.unitIndex, modType);
219
220            if (context.scopeChain.moduleDecl) {
221                typeSymbol.declModule = context.scopeChain.moduleDecl;
222            }
223            typeSymbol.declAST = moduleDecl;
224            typeSymbol.prettyName = moduleDecl.prettyName;
225            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,
226                                    context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
227            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol,
228                                    context.checker.errorReporter, isExported || isGlobal, false, isAmbient);
229            modType.symbol = typeSymbol;
230        }
231        else {
232            if (symbol && symbol.declAST && symbol.declAST.nodeType != NodeType.ModuleDeclaration) {
233                context.checker.errorReporter.simpleError(moduleDecl, "Conflicting symbol name for module '" + modName + "'");
234            }
235            typeSymbol = <TypeSymbol>symbol;
236
237            // initialize new private scope for the type
238            var publicEnclosedTypes = typeSymbol.type.getAllEnclosedTypes().publicMembers;
239            var publicEnclosedTypesTable = (publicEnclosedTypes == null) ? new StringHashTable() : publicEnclosedTypes;
240            var enclosedTypes = new ScopedMembers(new DualStringHashTable(publicEnclosedTypesTable, new StringHashTable()));
241
242            var publicEnclosedAmbientTypes = typeSymbol.type.getAllAmbientEnclosedTypes().publicMembers;
243            var publicAmbientEnclosedTypesTable = (publicEnclosedAmbientTypes == null) ? new StringHashTable() : publicEnclosedAmbientTypes;
244            var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(publicAmbientEnclosedTypesTable, new StringHashTable()));
245
246            var publicMembers = typeSymbol.type.members.publicMembers;
247            var publicMembersTable = (publicMembers == null) ? new StringHashTable() : publicMembers;
248            var members = new ScopedMembers(new DualStringHashTable(publicMembersTable, new StringHashTable()));
249
250            var publicAmbientMembers = typeSymbol.type.ambientMembers.publicMembers;
251            var publicAmbientMembersTable = (publicAmbientMembers == null) ? new StringHashTable() : publicAmbientMembers;
252            var ambientMembers = new ScopedMembers(new DualStringHashTable(publicAmbientMembersTable, new StringHashTable()));
253
254            modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);
255            if (isEnum) {
256                modType.typeFlags |= TypeFlags.IsEnum;
257            }
258            modType.members = members;
259            modType.ambientMembers = ambientMembers;
260            modType.setHasImplementation();
261            modType.symbol = typeSymbol;
262
263            typeSymbol.addLocation(moduleDecl.minChar);
264            typeSymbol.expansions.push(modType);
265
266        }
267        if (context.scopeChain.moduleDecl) {
268            context.scopeChain.moduleDecl.recordNonInterface();
269        }
270        // REVIEW: If multiple disparate module decls for the same module don't agree
271        // in export privileges, how should we handle it?
272        if (isExported) {
273            typeSymbol.flags |= SymbolFlags.Exported;
274        }
275        if ((context.scopeChain.moduleDecl) ||
276            (context.scopeChain.container == context.checker.gloMod)) {
277            typeSymbol.flags |= SymbolFlags.ModuleMember;
278        }
279
280        moduleDecl.mod = modType;
281        pushTypeCollectionScope(typeSymbol, modType.members,
282                                modType.ambientMembers,
283                                modType.enclosedTypes,
284                                modType.ambientEnclosedTypes,
285                                context, null, null, moduleDecl);
286
287        return true;
288    }
289
290    export function preCollectClassTypes(ast: AST, parent: AST, context: TypeCollectionContext) {
291        var scopeChain = context.scopeChain;
292        var classDecl = <ClassDeclaration>ast;
293
294        var classType: Type;
295        var instanceType: Type;
296        var typeSymbol: TypeSymbol = null;
297        var className = (<Identifier>classDecl.name).text;
298        var alreadyInScope = false;
299        var isAmbient = hasFlag(classDecl.varFlags, VarFlags.Ambient);
300        var isExported = hasFlag(classDecl.varFlags, VarFlags.Exported);
301        var isGlobal = context.scopeChain.container == context.checker.gloMod;
302        var containerMod = <TypeSymbol>scopeChain.container;
303        var foundValSymbol = false;
304
305        typeSymbol = <TypeSymbol>scopeChain.scope.findLocal(className, false, true);
306
307        // check the value space, since an override may have been declared with the type's name
308        // REVIEW-CLASSES
309        if (!typeSymbol) {
310            var valTypeSymbol = scopeChain.scope.findLocal(className, false, false);
311
312            if (valTypeSymbol &&
313                valTypeSymbol.isType() &&
314                valTypeSymbol.declAST &&
315                valTypeSymbol.declAST.nodeType == NodeType.FuncDecl &&
316                (<FuncDecl>valTypeSymbol.declAST).isSignature()) {
317
318                typeSymbol = <TypeSymbol>valTypeSymbol;
319                foundValSymbol = true;
320
321                if (isExported) {
322                    typeSymbol.flags |= SymbolFlags.Exported;
323                }
324
325                if (isAmbient) {
326                    typeSymbol.flags |= SymbolFlags.Ambient;
327                }
328
329                // the class was never entered into type space, so add it
330                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,
331                                            context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
332            }
333        }
334
335        if (typeSymbol && !foundValSymbol && (typeSymbol.declAST != classDecl)) {
336            typeSymbol = null;
337        }
338
339        if (typeSymbol == null) {
340            var valueSymbol = scopeChain.scope.findLocal(className, false, false);
341            classType = new Type();
342            classType.setHasImplementation();
343            instanceType = new Type();
344            instanceType.setHasImplementation();
345            classType.instanceType = instanceType;
346            classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
347            classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
348            addPrototypeField(classType, classDecl, context);
349            instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
350            instanceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
351            typeSymbol = new TypeSymbol(className, classDecl.minChar,
352                                        context.checker.locationInfo.unitIndex, classType);
353            typeSymbol.declAST = classDecl;
354            typeSymbol.instanceType = instanceType;
355            classType.symbol = typeSymbol;
356            instanceType.symbol = typeSymbol;
357
358            if (context.scopeChain.moduleDecl) {
359                context.scopeChain.moduleDecl.recordNonInterface();
360                typeSymbol.declModule = context.scopeChain.moduleDecl;
361                typeSymbol.flags |= SymbolFlags.ModuleMember;
362            }
363
364            if (isExported) {
365                typeSymbol.flags |= SymbolFlags.Exported;
366            }
367
368            if (isAmbient) {
369                typeSymbol.flags |= SymbolFlags.Ambient;
370            }
371
372            ast.type = classType;
373
374            // class in both name spaces (type for instance type; constructor representative in value space)
375            context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,
376                                            context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
377
378            if (valueSymbol == null) {
379                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol,
380                                            context.checker.errorReporter, isExported || isGlobal, false, isAmbient);
381            }
382        }
383        else {
384            classType = typeSymbol.type;
385
386            // If the instance type is null, a call overload was likely declared before the class constructor
387            if (classType.instanceType == null) {
388                classType.instanceType = new Type();
389                classType.instanceType.setHasImplementation();
390                classType.instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
391                classType.instanceType.symbol = classType.symbol;
392                classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
393                classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
394            }
395
396            instanceType = classType.instanceType;
397            ast.type = classType;
398        }
399
400        // if the class has no declared constructor, either create a default signature or adapt
401        // it's base class's signature group
402        if (!classDecl.constructorDecl) {
403
404            if (typeSymbol && typeSymbol.declAST && typeSymbol.declAST.type && typeSymbol.declAST.type.call && !(<FuncDecl>typeSymbol.declAST).isOverload) {
405                context.checker.errorReporter.duplicateIdentifier(typeSymbol.declAST, typeSymbol.name);
406            }
407
408            createNewConstructGroupForType(classDecl.type);
409        }
410
411        classType.typeFlags |= TypeFlags.IsClass;
412        instanceType.typeFlags |= TypeFlags.IsClass;
413
414        getBases(instanceType, classDecl);
415        pushTypeCollectionScope(typeSymbol, instanceType.members, instanceType.ambientMembers, null, null,
416                                context, instanceType, classType, null);
417        return true;
418    }
419
420    export function preCollectInterfaceTypes(ast: AST, parent: AST, context: TypeCollectionContext) {
421        var scopeChain = context.scopeChain;
422        var interfaceDecl = <InterfaceDeclaration>ast;
423        var interfaceSymbol: TypeSymbol = null;
424        var interfaceType: Type = null;
425        var isExported = hasFlag(interfaceDecl.varFlags, VarFlags.Exported);
426        var isGlobal = context.scopeChain.container == context.checker.gloMod;
427        var alreadyInScope = true;
428
429        alreadyInScope = false;
430        var interfaceName = (<Identifier>interfaceDecl.name).text;
431        interfaceSymbol = <TypeSymbol>scopeChain.scope.findLocal(interfaceName, false, true);
432        if (interfaceSymbol == null) {
433            interfaceType = new Type();
434            interfaceSymbol = new TypeSymbol(interfaceName,
435                                        ast.minChar,
436                                        context.checker.locationInfo.unitIndex,
437                                        interfaceType);
438            interfaceType.symbol = interfaceSymbol;
439            // REVIEW: Shouldn't allocate another table for interface privates
440            interfaceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
441            interfaceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
442            interfaceSymbol.declAST = interfaceDecl;
443            interfaceSymbol.declModule = context.scopeChain.moduleDecl;
444        }
445        else {
446            alreadyInScope = true;
447            interfaceType = interfaceSymbol.type;
448        }
449
450        if (!interfaceType) {
451            interfaceType = context.checker.anyType;
452        }
453
454        ast.type = interfaceType;
455        getBases(interfaceType, interfaceDecl);
456
457        if (isExported) {
458            interfaceSymbol.flags |= SymbolFlags.Exported;
459        }
460
461        if (context.scopeChain.moduleDecl) {
462            interfaceSymbol.flags |= SymbolFlags.ModuleMember;
463        }
464
465        if (!alreadyInScope) {
466            context.scopeChain.scope.enter(context.scopeChain.container, ast,
467                                            interfaceSymbol, context.checker.errorReporter, isGlobal || isExported, true, false); // REVIEW: Technically, interfaces should be ambient
468        }
469        pushTypeCollectionScope(interfaceSymbol, interfaceType.members, interfaceType.ambientMembers, null, null,
470                                context, interfaceType, null, null);
471        return true;
472    }
473
474    export function preCollectArgDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {
475        var scopeChain = context.scopeChain;
476        var argDecl = <ArgDecl>ast;
477        if (hasFlag(argDecl.varFlags, VarFlags.Public | VarFlags.Private)) {
478            var field = new ValueLocation();
479            var isPrivate = hasFlag(argDecl.varFlags, VarFlags.Private);
480            var fieldSymbol =
481                new FieldSymbol(argDecl.id.text, argDecl.minChar,
482                                context.checker.locationInfo.unitIndex,
483                                !hasFlag(argDecl.varFlags, VarFlags.Readonly),
484                                field);
485            fieldSymbol.transferVarFlags(argDecl.varFlags);
486            field.symbol = fieldSymbol;
487            fieldSymbol.declAST = ast;
488            argDecl.parameterPropertySym = fieldSymbol;
489
490            context.scopeChain.scope.enter(context.scopeChain.container, ast,
491                                            fieldSymbol, context.checker.errorReporter, !isPrivate, false, false);
492
493            field.typeLink = getTypeLink(argDecl.typeExpr, context.checker, argDecl.init == null);
494            argDecl.sym = fieldSymbol;
495        }
496        return false;
497    }
498
499    export function preCollectVarDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {
500        var scopeChain = context.scopeChain;
501        var varDecl = <VarDecl>ast;
502        var isAmbient = hasFlag(varDecl.varFlags, VarFlags.Ambient);
503        var isExported = hasFlag(varDecl.varFlags, VarFlags.Exported);
504        var isGlobal = context.scopeChain.container == context.checker.gloMod;
505        var isProperty = hasFlag(varDecl.varFlags, VarFlags.Property);
506        var isStatic = hasFlag(varDecl.varFlags, VarFlags.Static);
507        var isPrivate = hasFlag(varDecl.varFlags, VarFlags.Private);
508        var isOptional = hasFlag(varDecl.id.flags, ASTFlags.OptionalName);
509
510        if (context.scopeChain.moduleDecl) {
511            context.scopeChain.moduleDecl.recordNonInterface();
512        }
513        if (isProperty ||
514            isExported ||
515            (context.scopeChain.container == context.checker.gloMod) ||
516            context.scopeChain.moduleDecl) {
517            if (isAmbient) {
518                var existingSym =
519                    <FieldSymbol>scopeChain.scope.findLocal(varDecl.id.text, false, false);
520                if (existingSym) {
521                    varDecl.sym = existingSym;
522                    return false;
523                }
524            }
525
526            // Defensive error detection...
527            if (varDecl.id == null) {
528                context.checker.errorReporter.simpleError(varDecl, "Expected variable identifier at this location");
529                return false;
530            }
531
532            var field = new ValueLocation();
533            var fieldSymbol =
534                new FieldSymbol(varDecl.id.text, varDecl.minChar,
535                                context.checker.locationInfo.unitIndex,
536                                (varDecl.varFlags & VarFlags.Readonly) == VarFlags.None,
537                                field);
538            fieldSymbol.transferVarFlags(varDecl.varFlags);
539            if (isOptional) {
540                fieldSymbol.flags |= SymbolFlags.Optional;
541            }
542            field.symbol = fieldSymbol;
543            fieldSymbol.declAST = ast;
544            if ((context.scopeChain.moduleDecl) ||
545                (context.scopeChain.container == context.checker.gloMod)) {
546                fieldSymbol.flags |= SymbolFlags.ModuleMember;
547                fieldSymbol.declModule = context.scopeChain.moduleDecl;
548            }
549
550            // if it's static, enter it into the class's member list directly
551            if (hasFlag(varDecl.varFlags, VarFlags.Property) && isStatic && context.scopeChain.classType) {
552                if (!context.scopeChain.classType.members.publicMembers.add(varDecl.id.text, fieldSymbol)) {
553                    context.checker.errorReporter.duplicateIdentifier(ast, fieldSymbol.name);
554                }
555                fieldSymbol.container = context.scopeChain.classType.symbol;
556            }
557            else {
558                context.scopeChain.scope.enter(context.scopeChain.container,
559                                                ast,
560                                                fieldSymbol,
561                                                context.checker.errorReporter,
562                                                !isPrivate && (isProperty || isExported || isGlobal || isStatic),
563                                                false,
564                                                isAmbient);
565            }
566
567            if (hasFlag(varDecl.varFlags, VarFlags.Exported)) {
568                fieldSymbol.flags |= SymbolFlags.Exported;
569            }
570
571            field.typeLink = getTypeLink(varDecl.typeExpr, context.checker,
572                                        varDecl.init == null);
573            varDecl.sym = fieldSymbol;
574        }
575        return false;
576    }
577
578    export function preCollectFuncDeclTypes(ast: AST, parent: AST, context: TypeCollectionContext) {
579        var scopeChain = context.scopeChain;
580
581        // REVIEW: This will have to change when we move to "export"
582        if (context.scopeChain.moduleDecl) {
583            context.scopeChain.moduleDecl.recordNonInterface();
584        }
585
586        var funcDecl = <FuncDecl>ast;
587        var fgSym: TypeSymbol = null;
588        var nameText = funcDecl.getNameText();
589        var isExported = hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported);
590        var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);
591        var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);
592        var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;
593        var containerSym:TypeSymbol = <TypeSymbol> (((funcDecl.isMethod() && isStatic) || funcDecl.isAccessor()) && context.scopeChain.classType ? context.scopeChain.classType.symbol : context.scopeChain.container);
594        var containerScope: SymbolScope = context.scopeChain.scope;
595        var isGlobal = containerSym == context.checker.gloMod;
596        var isOptional = funcDecl.name && hasFlag(funcDecl.name.flags, ASTFlags.OptionalName);
597        var go = false;
598        var foundSymbol = false;
599
600        // If this is a class constructor, the "container" is actually the class declaration
601        if (isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {
602            containerSym = <TypeSymbol>containerSym.container;
603            containerScope = scopeChain.previous.scope;
604        }
605
606        funcDecl.unitIndex = context.checker.locationInfo.unitIndex;
607
608        // If the parent is the constructor, and this isn't an instance method, skip it.
609        // That way, we'll set the type during scope assignment, and can be sure that the
610        // function will be placed in the constructor-local scope
611        if (!funcDecl.isConstructor &&
612            containerSym &&
613            containerSym.declAST &&
614            containerSym.declAST.nodeType == NodeType.FuncDecl &&
615            (<FuncDecl>containerSym.declAST).isConstructor &&
616            !funcDecl.isMethod()) {
617            return go;
618        }
619
620        // Interfaces and overloads
621        if (hasFlag(funcDecl.fncFlags, FncFlags.Signature)) {
622            var instType = context.scopeChain.thisType;
623
624            // If the function is static, search in the class type's
625            if (nameText && nameText != "__missing") {
626                if (isStatic) {
627                    fgSym = containerSym.type.members.allMembers.lookup(nameText);
628                }
629                else {
630                    // REVIEW: This logic should be symmetric with preCollectClassTypes
631                    fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, false);
632
633                    // If we could not find the function symbol in the value context, look
634                    // in the type context.
635                    // This would be the case, for example, if a class constructor override
636                    // were declared before a call override for a given class
637                    if (fgSym == null) {
638                        fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, true);
639                    }
640                }
641
642                if (fgSym) {
643                    foundSymbol = true;
644
645                    // We'll combine ambient and non-ambient funcdecls during typecheck (for contextual typing).,
646                    // So, if they don't agree, don't use the symbol we've found
647                    if (!funcDecl.isSignature() && (hasFlag(funcDecl.fncFlags, FncFlags.Ambient) != hasFlag(fgSym.flags, SymbolFlags.Ambient))) {
648                       fgSym = null;
649                    }
650                }
651            }
652
653            // a function with this symbol has not yet been declared in this scope
654            // REVIEW: In the code below, we need to ensure that only function overloads are considered
655            //  (E.g., if a vardecl has the same id as a function or class, we may use the vardecl symbol
656            //  as the overload.)  Defensively, however, the vardecl won't have a type yet, so it should
657            //  suffice to just check for a null type when considering the overload symbol in
658            //  createFunctionSignature
659            if (fgSym == null) {
660                if (!(funcDecl.isSpecialFn())) {
661                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, null, !foundSymbol).declAST.type.symbol;
662                }
663                else {
664                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, containerSym, false).declAST.type.symbol;
665                }
666
667                // set the symbol's declAST, which will point back to the first declaration (symbol or otherwise)
668                // related to this symbol
669                if (fgSym.declAST == null || !funcDecl.isSpecialFn()) {
670                    fgSym.declAST = ast;
671                }
672            }
673            else { // there exists a symbol with this name
674
675                if ((fgSym.kind() == SymbolKind.Type)) {
676
677                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, false).declAST.type.symbol;
678                }
679                else {
680                    context.checker.errorReporter.simpleError(funcDecl, "Function or method '" + funcDecl.name.actualText + "' already declared as a property");
681                }
682            }
683
684            if (funcDecl.isSpecialFn() && !isStatic) {
685                funcDecl.type = instType ? instType : fgSym.type;
686            }
687            else {
688                funcDecl.type = fgSym.type;
689            }
690        }
691        else {
692            // declarations
693
694            if (nameText) {
695                if (isStatic) {
696                    fgSym = containerSym.type.members.allMembers.lookup(nameText);
697                }
698                else {
699                    // in the constructor case, we want to check the parent scope for overloads
700                    if (funcDecl.isConstructor && context.scopeChain.previous) {
701                        fgSym = <TypeSymbol>context.scopeChain.previous.scope.findLocal(nameText, false, false);
702                    }
703
704                    if (fgSym == null) {
705                        fgSym = <TypeSymbol>containerScope.findLocal(nameText, false, false);
706                    }
707                }
708                if (fgSym) {
709                    foundSymbol = true;
710
711                    if (!isConstructor && fgSym.declAST.nodeType == NodeType.FuncDecl && !(<FuncDecl>fgSym.declAST).isAccessor() && !(<FuncDecl>fgSym.declAST).isSignature()) {
712                        fgSym = null;
713                        foundSymbol = false;
714                    }
715                }
716            }
717
718            // REVIEW: Move this check into the typecheck phase?  It's only being run over properties...
719            if (fgSym &&
720                !fgSym.isAccessor() &&
721                fgSym.type &&
722                fgSym.type.construct &&
723                fgSym.type.construct.signatures != [] &&
724                (fgSym.type.construct.signatures[0].declAST == null ||
725                    !hasFlag(fgSym.type.construct.signatures[0].declAST.fncFlags, FncFlags.Ambient)) &&
726                !funcDecl.isConstructor) {
727                context.checker.errorReporter.simpleError(funcDecl, "Functions may not have class overloads");
728            }
729
730            if (fgSym && !(fgSym.kind() == SymbolKind.Type) && funcDecl.isMethod() && !funcDecl.isAccessor() && !funcDecl.isConstructor) {
731                context.checker.errorReporter.simpleError(funcDecl, "Function or method '" + funcDecl.name.actualText + "' already declared as a property");
732                fgSym.type = context.checker.anyType;
733            }
734            var sig = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, !foundSymbol);
735
736            // it's a getter or setter function
737            if (((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) || (fgSym && fgSym.isAccessor())) {
738                funcDecl.accessorSymbol = context.checker.createAccessorSymbol(funcDecl, fgSym, containerSym.type, (funcDecl.isMethod() && isStatic), true, containerScope, containerSym);
739            }
740
741            funcDecl.type.symbol.declAST = ast;
742            if (funcDecl.isConstructor) { // REVIEW: Remove when classes completely replace oldclass
743                go = true;
744            };
745        }
746        if (isExported) {
747            if (funcDecl.type.call) {
748                funcDecl.type.symbol.flags |= SymbolFlags.Exported;
749            }
750
751            // Accessors are set to 'exported' above
752            if (fgSym && !fgSym.isAccessor() && fgSym.kind() == SymbolKind.Type && fgSym.type.call) {
753                fgSym.flags |= SymbolFlags.Exported;
754            }
755        }
756        if (context.scopeChain.moduleDecl && !funcDecl.isSpecialFn()) {
757            funcDecl.type.symbol.flags |= SymbolFlags.ModuleMember;
758            funcDecl.type.symbol.declModule = context.scopeChain.moduleDecl;
759        }
760
761        if (fgSym && isOptional) {
762            fgSym.flags |= SymbolFlags.Optional;
763        }
764
765        return go;
766    }
767
768    export function preCollectTypes(ast: AST, parent: AST, walker: IAstWalker) {
769        var context: TypeCollectionContext = walker.state;
770        var go = false;
771        var scopeChain = context.scopeChain;
772
773        if (ast.nodeType == NodeType.Script) {
774            var script: Script = <Script>ast;
775            context.script = script;
776            go = true;
777        }
778        else if (ast.nodeType == NodeType.List) {
779            go = true;
780        }
781        else if (ast.nodeType == NodeType.ImportDeclaration) {
782            go = preCollectImportTypes(ast, parent, context);
783        }
784        else if (ast.nodeType == NodeType.With) {
785            go = false;
786        }
787        else if (ast.nodeType == NodeType.ModuleDeclaration) {
788            go = preCollectModuleTypes(ast, parent, context);
789        }
790        else if (ast.nodeType == NodeType.ClassDeclaration) {
791            go = preCollectClassTypes(ast, parent, context);
792        }
793        else if (ast.nodeType == NodeType.Block) {
794            go = true;
795        }
796        else if (ast.nodeType == NodeType.InterfaceDeclaration) {
797            go = preCollectInterfaceTypes(ast, parent, context);
798        }
799        // This will be a constructor arg because this pass only traverses
800        // constructor arg lists
801        else if (ast.nodeType == NodeType.ArgDecl) {
802            go = preCollectArgDeclTypes(ast, parent, context);
803        }
804        else if (ast.nodeType == NodeType.VarDecl) {
805            go = preCollectVarDeclTypes(ast, parent, context);
806        }
807        else if (ast.nodeType == NodeType.FuncDecl) {
808            go = preCollectFuncDeclTypes(ast, parent, context);
809        }
810        else {
811            if (ast.isStatementOrExpression() && context.scopeChain.moduleDecl) {
812                context.scopeChain.moduleDecl.recordNonInterface();
813            }
814        }
815        walker.options.goChildren = go;
816        return ast;
817    }
818
819    export function postCollectTypes(ast: AST, parent: AST, walker: IAstWalker) {
820        var context: TypeCollectionContext = walker.state;
821
822        if (ast.nodeType == NodeType.ModuleDeclaration) {
823            popTypeCollectionScope(context);
824        }
825        else if (ast.nodeType == NodeType.ClassDeclaration) {
826            popTypeCollectionScope(context);
827        }
828        else if (ast.nodeType == NodeType.InterfaceDeclaration) {
829            popTypeCollectionScope(context);
830        }
831        return ast;
832    }
833
834}
835
836//// [parserRealSource7.js]
837// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
838// See LICENSE.txt in the project root for complete license information.
839///<reference path='typescript.ts' />
840var TypeScript;
841(function (TypeScript) {
842    var Continuation = /** @class */ (function () {
843        function Continuation(normalBlock) {
844            this.normalBlock = normalBlock;
845            this.exceptionBlock = -1;
846        }
847        return Continuation;
848    }());
849    TypeScript.Continuation = Continuation;
850    function getBaseTypeLinks(bases, baseTypeLinks) {
851        if (bases) {
852            var len = bases.members.length;
853            if (baseTypeLinks == null) {
854                baseTypeLinks = new TypeLink[];
855            }
856            for (var i = 0; i < len; i++) {
857                var baseExpr = bases.members[i];
858                var name = baseExpr;
859                var typeLink = new TypeLink();
860                typeLink.ast = name;
861                baseTypeLinks[baseTypeLinks.length] = typeLink;
862            }
863        }
864        return baseTypeLinks;
865    }
866    function getBases(type, typeDecl) {
867        type.extendsTypeLinks = getBaseTypeLinks(typeDecl.extendsList, type.extendsTypeLinks);
868        type.implementsTypeLinks = getBaseTypeLinks(typeDecl.implementsList, type.implementsTypeLinks);
869    }
870    function addPrototypeField(classType, ast, context) {
871        var field = new ValueLocation();
872        field.typeLink = new TypeLink();
873        field.typeLink.ast = ast;
874        field.typeLink.type = classType.instanceType;
875        var fieldSymbol = new FieldSymbol("prototype", ast.minChar, context.checker.locationInfo.unitIndex, true, field);
876        fieldSymbol.flags |= (SymbolFlags.Property | SymbolFlags.BuiltIn);
877        field.symbol = fieldSymbol;
878        fieldSymbol.declAST = ast;
879        classType.members.addPublicMember("prototype", fieldSymbol);
880    }
881    function createNewConstructGroupForType(type) {
882        var signature = new Signature();
883        signature.returnType = new TypeLink();
884        signature.returnType.type = type.instanceType;
885        signature.parameters = [];
886        type.construct = new SignatureGroup();
887        type.construct.addSignature(signature);
888    }
889    TypeScript.createNewConstructGroupForType = createNewConstructGroupForType;
890    function cloneParentConstructGroupForChildType(child, parent) {
891        child.construct = new SignatureGroup();
892        var sig = null;
893        if (!parent.construct) {
894            createNewConstructGroupForType(parent);
895        }
896        for (var i = 0; i < parent.construct.signatures.length; i++) {
897            sig = new Signature();
898            sig.parameters = parent.construct.signatures[i].parameters;
899            sig.nonOptionalParameterCount = parent.construct.signatures[i].nonOptionalParameterCount;
900            sig.typeCheckStatus = parent.construct.signatures[i].typeCheckStatus;
901            sig.declAST = parent.construct.signatures[i].declAST;
902            sig.returnType = new TypeLink();
903            sig.returnType.type = child.instanceType;
904            child.construct.addSignature(sig);
905        }
906    }
907    TypeScript.cloneParentConstructGroupForChildType = cloneParentConstructGroupForChildType;
908    TypeScript.globalId = "__GLO";
909    function findTypeSymbolInScopeChain(name, scopeChain) {
910        var symbol = scopeChain.scope.find(name, false, true);
911        if (symbol == null && scopeChain.previous) {
912            symbol = findTypeSymbolInScopeChain(name, scopeChain.previous);
913        }
914        return symbol;
915    }
916    function findSymbolFromAlias(alias, context) {
917        var symbol = null;
918        switch (alias.nodeType) {
919            case NodeType.Name:
920                var name = alias.text;
921                var isDynamic = isQuoted(name);
922                var findSym = function (id) {
923                    if (context.members) {
924                        return context.members.lookup(name);
925                    }
926                    else {
927                        return findTypeSymbolInScopeChain(name, context.topLevelScope);
928                    }
929                };
930                if (isDynamic) {
931                    symbol = context.tcContext.checker.findSymbolForDynamicModule(name, context.tcContext.script.locationInfo.filename, findSym);
932                }
933                else {
934                    symbol = findSym(name);
935                }
936                break;
937            case NodeType.Dot:
938                var dottedExpr = alias;
939                var op1Sym = findSymbolFromAlias(dottedExpr.operand1, context);
940                if (op1Sym && op1Sym.getType()) {
941                    symbol = findSymbolFromAlias(dottedExpr.operand2, context);
942                }
943                break;
944            default:
945                break;
946        }
947        if (symbol) {
948            var symType = symbol.getType();
949            if (symType) {
950                var members = symType.members;
951                if (members) {
952                    context.members = members.publicMembers;
953                }
954            }
955        }
956        return symbol;
957    }
958    function preCollectImportTypes(ast, parent, context) {
959        var scopeChain = context.scopeChain;
960        var typeSymbol = null;
961        var modType = null;
962        var importDecl = ast;
963        var isExported = hasFlag(importDecl.varFlags, VarFlags.Exported);
964        // REVIEW: technically, this call isn't strictly necessary, since we'll find the type during the call to resolveTypeMembers
965        var aliasedModSymbol = findSymbolFromAlias(importDecl.alias, { topLevelScope: scopeChain, members: null, tcContext: context });
966        var isGlobal = context.scopeChain.container == context.checker.gloMod;
967        if (aliasedModSymbol) {
968            var aliasedModType = aliasedModSymbol.getType();
969            if (aliasedModType) {
970                modType = aliasedModType;
971            }
972        }
973        typeSymbol = new TypeSymbol(importDecl.id.text, importDecl.minChar, context.checker.locationInfo.unitIndex, modType);
974        typeSymbol.aliasLink = importDecl;
975        if (context.scopeChain.moduleDecl) {
976            typeSymbol.declModule = context.scopeChain.moduleDecl;
977        }
978        typeSymbol.declAST = importDecl;
979        importDecl.id.sym = typeSymbol;
980        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, true, false);
981        scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, false, false);
982        return true;
983    }
984    TypeScript.preCollectImportTypes = preCollectImportTypes;
985    function preCollectModuleTypes(ast, parent, context) {
986        var scopeChain = context.scopeChain;
987        var moduleDecl = ast;
988        var isAmbient = hasFlag(moduleDecl.modFlags, ModuleFlags.Ambient);
989        var isEnum = hasFlag(moduleDecl.modFlags, ModuleFlags.IsEnum);
990        var isGlobal = context.scopeChain.container == context.checker.gloMod;
991        var isExported = hasFlag(moduleDecl.modFlags, ModuleFlags.Exported);
992        var modName = moduleDecl.name.text;
993        var isDynamic = isQuoted(modName);
994        var symbol = scopeChain.scope.findLocal(modName, false, false);
995        var typeSymbol = null;
996        var modType = null;
997        if ((symbol == null) || (symbol.kind() != SymbolKind.Type)) {
998            if (modType == null) {
999                var enclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1000                var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1001                modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);
1002                if (isEnum) {
1003                    modType.typeFlags |= TypeFlags.IsEnum;
1004                }
1005                modType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1006                modType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1007                modType.setHasImplementation();
1008            }
1009            typeSymbol = new TypeSymbol(modName, moduleDecl.minChar, context.checker.locationInfo.unitIndex, modType);
1010            if (context.scopeChain.moduleDecl) {
1011                typeSymbol.declModule = context.scopeChain.moduleDecl;
1012            }
1013            typeSymbol.declAST = moduleDecl;
1014            typeSymbol.prettyName = moduleDecl.prettyName;
1015            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
1016            scopeChain.scope.enter(scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, false, isAmbient);
1017            modType.symbol = typeSymbol;
1018        }
1019        else {
1020            if (symbol && symbol.declAST && symbol.declAST.nodeType != NodeType.ModuleDeclaration) {
1021                context.checker.errorReporter.simpleError(moduleDecl, "Conflicting symbol name for module '" + modName + "'");
1022            }
1023            typeSymbol = symbol;
1024            // initialize new private scope for the type
1025            var publicEnclosedTypes = typeSymbol.type.getAllEnclosedTypes().publicMembers;
1026            var publicEnclosedTypesTable = (publicEnclosedTypes == null) ? new StringHashTable() : publicEnclosedTypes;
1027            var enclosedTypes = new ScopedMembers(new DualStringHashTable(publicEnclosedTypesTable, new StringHashTable()));
1028            var publicEnclosedAmbientTypes = typeSymbol.type.getAllAmbientEnclosedTypes().publicMembers;
1029            var publicAmbientEnclosedTypesTable = (publicEnclosedAmbientTypes == null) ? new StringHashTable() : publicEnclosedAmbientTypes;
1030            var ambientEnclosedTypes = new ScopedMembers(new DualStringHashTable(publicAmbientEnclosedTypesTable, new StringHashTable()));
1031            var publicMembers = typeSymbol.type.members.publicMembers;
1032            var publicMembersTable = (publicMembers == null) ? new StringHashTable() : publicMembers;
1033            var members = new ScopedMembers(new DualStringHashTable(publicMembersTable, new StringHashTable()));
1034            var publicAmbientMembers = typeSymbol.type.ambientMembers.publicMembers;
1035            var publicAmbientMembersTable = (publicAmbientMembers == null) ? new StringHashTable() : publicAmbientMembers;
1036            var ambientMembers = new ScopedMembers(new DualStringHashTable(publicAmbientMembersTable, new StringHashTable()));
1037            modType = new ModuleType(enclosedTypes, ambientEnclosedTypes);
1038            if (isEnum) {
1039                modType.typeFlags |= TypeFlags.IsEnum;
1040            }
1041            modType.members = members;
1042            modType.ambientMembers = ambientMembers;
1043            modType.setHasImplementation();
1044            modType.symbol = typeSymbol;
1045            typeSymbol.addLocation(moduleDecl.minChar);
1046            typeSymbol.expansions.push(modType);
1047        }
1048        if (context.scopeChain.moduleDecl) {
1049            context.scopeChain.moduleDecl.recordNonInterface();
1050        }
1051        // REVIEW: If multiple disparate module decls for the same module don't agree
1052        // in export privileges, how should we handle it?
1053        if (isExported) {
1054            typeSymbol.flags |= SymbolFlags.Exported;
1055        }
1056        if ((context.scopeChain.moduleDecl) ||
1057            (context.scopeChain.container == context.checker.gloMod)) {
1058            typeSymbol.flags |= SymbolFlags.ModuleMember;
1059        }
1060        moduleDecl.mod = modType;
1061        pushTypeCollectionScope(typeSymbol, modType.members, modType.ambientMembers, modType.enclosedTypes, modType.ambientEnclosedTypes, context, null, null, moduleDecl);
1062        return true;
1063    }
1064    TypeScript.preCollectModuleTypes = preCollectModuleTypes;
1065    function preCollectClassTypes(ast, parent, context) {
1066        var scopeChain = context.scopeChain;
1067        var classDecl = ast;
1068        var classType;
1069        var instanceType;
1070        var typeSymbol = null;
1071        var className = classDecl.name.text;
1072        var alreadyInScope = false;
1073        var isAmbient = hasFlag(classDecl.varFlags, VarFlags.Ambient);
1074        var isExported = hasFlag(classDecl.varFlags, VarFlags.Exported);
1075        var isGlobal = context.scopeChain.container == context.checker.gloMod;
1076        var containerMod = scopeChain.container;
1077        var foundValSymbol = false;
1078        typeSymbol = scopeChain.scope.findLocal(className, false, true);
1079        // check the value space, since an override may have been declared with the type's name
1080        // REVIEW-CLASSES
1081        if (!typeSymbol) {
1082            var valTypeSymbol = scopeChain.scope.findLocal(className, false, false);
1083            if (valTypeSymbol &&
1084                valTypeSymbol.isType() &&
1085                valTypeSymbol.declAST &&
1086                valTypeSymbol.declAST.nodeType == NodeType.FuncDecl &&
1087                valTypeSymbol.declAST.isSignature()) {
1088                typeSymbol = valTypeSymbol;
1089                foundValSymbol = true;
1090                if (isExported) {
1091                    typeSymbol.flags |= SymbolFlags.Exported;
1092                }
1093                if (isAmbient) {
1094                    typeSymbol.flags |= SymbolFlags.Ambient;
1095                }
1096                // the class was never entered into type space, so add it
1097                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
1098            }
1099        }
1100        if (typeSymbol && !foundValSymbol && (typeSymbol.declAST != classDecl)) {
1101            typeSymbol = null;
1102        }
1103        if (typeSymbol == null) {
1104            var valueSymbol = scopeChain.scope.findLocal(className, false, false);
1105            classType = new Type();
1106            classType.setHasImplementation();
1107            instanceType = new Type();
1108            instanceType.setHasImplementation();
1109            classType.instanceType = instanceType;
1110            classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1111            classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1112            addPrototypeField(classType, classDecl, context);
1113            instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1114            instanceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1115            typeSymbol = new TypeSymbol(className, classDecl.minChar, context.checker.locationInfo.unitIndex, classType);
1116            typeSymbol.declAST = classDecl;
1117            typeSymbol.instanceType = instanceType;
1118            classType.symbol = typeSymbol;
1119            instanceType.symbol = typeSymbol;
1120            if (context.scopeChain.moduleDecl) {
1121                context.scopeChain.moduleDecl.recordNonInterface();
1122                typeSymbol.declModule = context.scopeChain.moduleDecl;
1123                typeSymbol.flags |= SymbolFlags.ModuleMember;
1124            }
1125            if (isExported) {
1126                typeSymbol.flags |= SymbolFlags.Exported;
1127            }
1128            if (isAmbient) {
1129                typeSymbol.flags |= SymbolFlags.Ambient;
1130            }
1131            ast.type = classType;
1132            // class in both name spaces (type for instance type; constructor representative in value space)
1133            context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, true, isAmbient);
1134            if (valueSymbol == null) {
1135                context.scopeChain.scope.enter(context.scopeChain.container, ast, typeSymbol, context.checker.errorReporter, isExported || isGlobal, false, isAmbient);
1136            }
1137        }
1138        else {
1139            classType = typeSymbol.type;
1140            // If the instance type is null, a call overload was likely declared before the class constructor
1141            if (classType.instanceType == null) {
1142                classType.instanceType = new Type();
1143                classType.instanceType.setHasImplementation();
1144                classType.instanceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1145                classType.instanceType.symbol = classType.symbol;
1146                classType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1147                classType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1148            }
1149            instanceType = classType.instanceType;
1150            ast.type = classType;
1151        }
1152        // if the class has no declared constructor, either create a default signature or adapt
1153        // it's base class's signature group
1154        if (!classDecl.constructorDecl) {
1155            if (typeSymbol && typeSymbol.declAST && typeSymbol.declAST.type && typeSymbol.declAST.type.call && !typeSymbol.declAST.isOverload) {
1156                context.checker.errorReporter.duplicateIdentifier(typeSymbol.declAST, typeSymbol.name);
1157            }
1158            createNewConstructGroupForType(classDecl.type);
1159        }
1160        classType.typeFlags |= TypeFlags.IsClass;
1161        instanceType.typeFlags |= TypeFlags.IsClass;
1162        getBases(instanceType, classDecl);
1163        pushTypeCollectionScope(typeSymbol, instanceType.members, instanceType.ambientMembers, null, null, context, instanceType, classType, null);
1164        return true;
1165    }
1166    TypeScript.preCollectClassTypes = preCollectClassTypes;
1167    function preCollectInterfaceTypes(ast, parent, context) {
1168        var scopeChain = context.scopeChain;
1169        var interfaceDecl = ast;
1170        var interfaceSymbol = null;
1171        var interfaceType = null;
1172        var isExported = hasFlag(interfaceDecl.varFlags, VarFlags.Exported);
1173        var isGlobal = context.scopeChain.container == context.checker.gloMod;
1174        var alreadyInScope = true;
1175        alreadyInScope = false;
1176        var interfaceName = interfaceDecl.name.text;
1177        interfaceSymbol = scopeChain.scope.findLocal(interfaceName, false, true);
1178        if (interfaceSymbol == null) {
1179            interfaceType = new Type();
1180            interfaceSymbol = new TypeSymbol(interfaceName, ast.minChar, context.checker.locationInfo.unitIndex, interfaceType);
1181            interfaceType.symbol = interfaceSymbol;
1182            // REVIEW: Shouldn't allocate another table for interface privates
1183            interfaceType.members = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1184            interfaceType.ambientMembers = new ScopedMembers(new DualStringHashTable(new StringHashTable(), new StringHashTable()));
1185            interfaceSymbol.declAST = interfaceDecl;
1186            interfaceSymbol.declModule = context.scopeChain.moduleDecl;
1187        }
1188        else {
1189            alreadyInScope = true;
1190            interfaceType = interfaceSymbol.type;
1191        }
1192        if (!interfaceType) {
1193            interfaceType = context.checker.anyType;
1194        }
1195        ast.type = interfaceType;
1196        getBases(interfaceType, interfaceDecl);
1197        if (isExported) {
1198            interfaceSymbol.flags |= SymbolFlags.Exported;
1199        }
1200        if (context.scopeChain.moduleDecl) {
1201            interfaceSymbol.flags |= SymbolFlags.ModuleMember;
1202        }
1203        if (!alreadyInScope) {
1204            context.scopeChain.scope.enter(context.scopeChain.container, ast, interfaceSymbol, context.checker.errorReporter, isGlobal || isExported, true, false); // REVIEW: Technically, interfaces should be ambient
1205        }
1206        pushTypeCollectionScope(interfaceSymbol, interfaceType.members, interfaceType.ambientMembers, null, null, context, interfaceType, null, null);
1207        return true;
1208    }
1209    TypeScript.preCollectInterfaceTypes = preCollectInterfaceTypes;
1210    function preCollectArgDeclTypes(ast, parent, context) {
1211        var scopeChain = context.scopeChain;
1212        var argDecl = ast;
1213        if (hasFlag(argDecl.varFlags, VarFlags.Public | VarFlags.Private)) {
1214            var field = new ValueLocation();
1215            var isPrivate = hasFlag(argDecl.varFlags, VarFlags.Private);
1216            var fieldSymbol = new FieldSymbol(argDecl.id.text, argDecl.minChar, context.checker.locationInfo.unitIndex, !hasFlag(argDecl.varFlags, VarFlags.Readonly), field);
1217            fieldSymbol.transferVarFlags(argDecl.varFlags);
1218            field.symbol = fieldSymbol;
1219            fieldSymbol.declAST = ast;
1220            argDecl.parameterPropertySym = fieldSymbol;
1221            context.scopeChain.scope.enter(context.scopeChain.container, ast, fieldSymbol, context.checker.errorReporter, !isPrivate, false, false);
1222            field.typeLink = getTypeLink(argDecl.typeExpr, context.checker, argDecl.init == null);
1223            argDecl.sym = fieldSymbol;
1224        }
1225        return false;
1226    }
1227    TypeScript.preCollectArgDeclTypes = preCollectArgDeclTypes;
1228    function preCollectVarDeclTypes(ast, parent, context) {
1229        var scopeChain = context.scopeChain;
1230        var varDecl = ast;
1231        var isAmbient = hasFlag(varDecl.varFlags, VarFlags.Ambient);
1232        var isExported = hasFlag(varDecl.varFlags, VarFlags.Exported);
1233        var isGlobal = context.scopeChain.container == context.checker.gloMod;
1234        var isProperty = hasFlag(varDecl.varFlags, VarFlags.Property);
1235        var isStatic = hasFlag(varDecl.varFlags, VarFlags.Static);
1236        var isPrivate = hasFlag(varDecl.varFlags, VarFlags.Private);
1237        var isOptional = hasFlag(varDecl.id.flags, ASTFlags.OptionalName);
1238        if (context.scopeChain.moduleDecl) {
1239            context.scopeChain.moduleDecl.recordNonInterface();
1240        }
1241        if (isProperty ||
1242            isExported ||
1243            (context.scopeChain.container == context.checker.gloMod) ||
1244            context.scopeChain.moduleDecl) {
1245            if (isAmbient) {
1246                var existingSym = scopeChain.scope.findLocal(varDecl.id.text, false, false);
1247                if (existingSym) {
1248                    varDecl.sym = existingSym;
1249                    return false;
1250                }
1251            }
1252            // Defensive error detection...
1253            if (varDecl.id == null) {
1254                context.checker.errorReporter.simpleError(varDecl, "Expected variable identifier at this location");
1255                return false;
1256            }
1257            var field = new ValueLocation();
1258            var fieldSymbol = new FieldSymbol(varDecl.id.text, varDecl.minChar, context.checker.locationInfo.unitIndex, (varDecl.varFlags & VarFlags.Readonly) == VarFlags.None, field);
1259            fieldSymbol.transferVarFlags(varDecl.varFlags);
1260            if (isOptional) {
1261                fieldSymbol.flags |= SymbolFlags.Optional;
1262            }
1263            field.symbol = fieldSymbol;
1264            fieldSymbol.declAST = ast;
1265            if ((context.scopeChain.moduleDecl) ||
1266                (context.scopeChain.container == context.checker.gloMod)) {
1267                fieldSymbol.flags |= SymbolFlags.ModuleMember;
1268                fieldSymbol.declModule = context.scopeChain.moduleDecl;
1269            }
1270            // if it's static, enter it into the class's member list directly
1271            if (hasFlag(varDecl.varFlags, VarFlags.Property) && isStatic && context.scopeChain.classType) {
1272                if (!context.scopeChain.classType.members.publicMembers.add(varDecl.id.text, fieldSymbol)) {
1273                    context.checker.errorReporter.duplicateIdentifier(ast, fieldSymbol.name);
1274                }
1275                fieldSymbol.container = context.scopeChain.classType.symbol;
1276            }
1277            else {
1278                context.scopeChain.scope.enter(context.scopeChain.container, ast, fieldSymbol, context.checker.errorReporter, !isPrivate && (isProperty || isExported || isGlobal || isStatic), false, isAmbient);
1279            }
1280            if (hasFlag(varDecl.varFlags, VarFlags.Exported)) {
1281                fieldSymbol.flags |= SymbolFlags.Exported;
1282            }
1283            field.typeLink = getTypeLink(varDecl.typeExpr, context.checker, varDecl.init == null);
1284            varDecl.sym = fieldSymbol;
1285        }
1286        return false;
1287    }
1288    TypeScript.preCollectVarDeclTypes = preCollectVarDeclTypes;
1289    function preCollectFuncDeclTypes(ast, parent, context) {
1290        var scopeChain = context.scopeChain;
1291        // REVIEW: This will have to change when we move to "export"
1292        if (context.scopeChain.moduleDecl) {
1293            context.scopeChain.moduleDecl.recordNonInterface();
1294        }
1295        var funcDecl = ast;
1296        var fgSym = null;
1297        var nameText = funcDecl.getNameText();
1298        var isExported = hasFlag(funcDecl.fncFlags, FncFlags.Exported | FncFlags.ClassPropertyMethodExported);
1299        var isStatic = hasFlag(funcDecl.fncFlags, FncFlags.Static);
1300        var isPrivate = hasFlag(funcDecl.fncFlags, FncFlags.Private);
1301        var isConstructor = funcDecl.isConstructMember() || funcDecl.isConstructor;
1302        var containerSym = (((funcDecl.isMethod() && isStatic) || funcDecl.isAccessor()) && context.scopeChain.classType ? context.scopeChain.classType.symbol : context.scopeChain.container);
1303        var containerScope = context.scopeChain.scope;
1304        var isGlobal = containerSym == context.checker.gloMod;
1305        var isOptional = funcDecl.name && hasFlag(funcDecl.name.flags, ASTFlags.OptionalName);
1306        var go = false;
1307        var foundSymbol = false;
1308        // If this is a class constructor, the "container" is actually the class declaration
1309        if (isConstructor && hasFlag(funcDecl.fncFlags, FncFlags.ClassMethod)) {
1310            containerSym = containerSym.container;
1311            containerScope = scopeChain.previous.scope;
1312        }
1313        funcDecl.unitIndex = context.checker.locationInfo.unitIndex;
1314        // If the parent is the constructor, and this isn't an instance method, skip it.
1315        // That way, we'll set the type during scope assignment, and can be sure that the
1316        // function will be placed in the constructor-local scope
1317        if (!funcDecl.isConstructor &&
1318            containerSym &&
1319            containerSym.declAST &&
1320            containerSym.declAST.nodeType == NodeType.FuncDecl &&
1321            containerSym.declAST.isConstructor &&
1322            !funcDecl.isMethod()) {
1323            return go;
1324        }
1325        // Interfaces and overloads
1326        if (hasFlag(funcDecl.fncFlags, FncFlags.Signature)) {
1327            var instType = context.scopeChain.thisType;
1328            // If the function is static, search in the class type's
1329            if (nameText && nameText != "__missing") {
1330                if (isStatic) {
1331                    fgSym = containerSym.type.members.allMembers.lookup(nameText);
1332                }
1333                else {
1334                    // REVIEW: This logic should be symmetric with preCollectClassTypes
1335                    fgSym = containerScope.findLocal(nameText, false, false);
1336                    // If we could not find the function symbol in the value context, look
1337                    // in the type context.
1338                    // This would be the case, for example, if a class constructor override
1339                    // were declared before a call override for a given class
1340                    if (fgSym == null) {
1341                        fgSym = containerScope.findLocal(nameText, false, true);
1342                    }
1343                }
1344                if (fgSym) {
1345                    foundSymbol = true;
1346                    // We'll combine ambient and non-ambient funcdecls during typecheck (for contextual typing).,
1347                    // So, if they don't agree, don't use the symbol we've found
1348                    if (!funcDecl.isSignature() && (hasFlag(funcDecl.fncFlags, FncFlags.Ambient) != hasFlag(fgSym.flags, SymbolFlags.Ambient))) {
1349                        fgSym = null;
1350                    }
1351                }
1352            }
1353            // a function with this symbol has not yet been declared in this scope
1354            // REVIEW: In the code below, we need to ensure that only function overloads are considered
1355            //  (E.g., if a vardecl has the same id as a function or class, we may use the vardecl symbol
1356            //  as the overload.)  Defensively, however, the vardecl won't have a type yet, so it should
1357            //  suffice to just check for a null type when considering the overload symbol in
1358            //  createFunctionSignature
1359            if (fgSym == null) {
1360                if (!(funcDecl.isSpecialFn())) {
1361                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, null, !foundSymbol).declAST.type.symbol;
1362                }
1363                else {
1364                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, containerSym, false).declAST.type.symbol;
1365                }
1366                // set the symbol's declAST, which will point back to the first declaration (symbol or otherwise)
1367                // related to this symbol
1368                if (fgSym.declAST == null || !funcDecl.isSpecialFn()) {
1369                    fgSym.declAST = ast;
1370                }
1371            }
1372            else { // there exists a symbol with this name
1373                if ((fgSym.kind() == SymbolKind.Type)) {
1374                    fgSym = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, false).declAST.type.symbol;
1375                }
1376                else {
1377                    context.checker.errorReporter.simpleError(funcDecl, "Function or method '" + funcDecl.name.actualText + "' already declared as a property");
1378                }
1379            }
1380            if (funcDecl.isSpecialFn() && !isStatic) {
1381                funcDecl.type = instType ? instType : fgSym.type;
1382            }
1383            else {
1384                funcDecl.type = fgSym.type;
1385            }
1386        }
1387        else {
1388            // declarations
1389            if (nameText) {
1390                if (isStatic) {
1391                    fgSym = containerSym.type.members.allMembers.lookup(nameText);
1392                }
1393                else {
1394                    // in the constructor case, we want to check the parent scope for overloads
1395                    if (funcDecl.isConstructor && context.scopeChain.previous) {
1396                        fgSym = context.scopeChain.previous.scope.findLocal(nameText, false, false);
1397                    }
1398                    if (fgSym == null) {
1399                        fgSym = containerScope.findLocal(nameText, false, false);
1400                    }
1401                }
1402                if (fgSym) {
1403                    foundSymbol = true;
1404                    if (!isConstructor && fgSym.declAST.nodeType == NodeType.FuncDecl && !fgSym.declAST.isAccessor() && !fgSym.declAST.isSignature()) {
1405                        fgSym = null;
1406                        foundSymbol = false;
1407                    }
1408                }
1409            }
1410            // REVIEW: Move this check into the typecheck phase?  It's only being run over properties...
1411            if (fgSym &&
1412                !fgSym.isAccessor() &&
1413                fgSym.type &&
1414                fgSym.type.construct &&
1415                fgSym.type.construct.signatures != [] &&
1416                (fgSym.type.construct.signatures[0].declAST == null ||
1417                    !hasFlag(fgSym.type.construct.signatures[0].declAST.fncFlags, FncFlags.Ambient)) &&
1418                !funcDecl.isConstructor) {
1419                context.checker.errorReporter.simpleError(funcDecl, "Functions may not have class overloads");
1420            }
1421            if (fgSym && !(fgSym.kind() == SymbolKind.Type) && funcDecl.isMethod() && !funcDecl.isAccessor() && !funcDecl.isConstructor) {
1422                context.checker.errorReporter.simpleError(funcDecl, "Function or method '" + funcDecl.name.actualText + "' already declared as a property");
1423                fgSym.type = context.checker.anyType;
1424            }
1425            var sig = context.checker.createFunctionSignature(funcDecl, containerSym, containerScope, fgSym, !foundSymbol);
1426            // it's a getter or setter function
1427            if (((!fgSym || fgSym.declAST.nodeType != NodeType.FuncDecl) && funcDecl.isAccessor()) || (fgSym && fgSym.isAccessor())) {
1428                funcDecl.accessorSymbol = context.checker.createAccessorSymbol(funcDecl, fgSym, containerSym.type, (funcDecl.isMethod() && isStatic), true, containerScope, containerSym);
1429            }
1430            funcDecl.type.symbol.declAST = ast;
1431            if (funcDecl.isConstructor) { // REVIEW: Remove when classes completely replace oldclass
1432                go = true;
1433            }
1434            ;
1435        }
1436        if (isExported) {
1437            if (funcDecl.type.call) {
1438                funcDecl.type.symbol.flags |= SymbolFlags.Exported;
1439            }
1440            // Accessors are set to 'exported' above
1441            if (fgSym && !fgSym.isAccessor() && fgSym.kind() == SymbolKind.Type && fgSym.type.call) {
1442                fgSym.flags |= SymbolFlags.Exported;
1443            }
1444        }
1445        if (context.scopeChain.moduleDecl && !funcDecl.isSpecialFn()) {
1446            funcDecl.type.symbol.flags |= SymbolFlags.ModuleMember;
1447            funcDecl.type.symbol.declModule = context.scopeChain.moduleDecl;
1448        }
1449        if (fgSym && isOptional) {
1450            fgSym.flags |= SymbolFlags.Optional;
1451        }
1452        return go;
1453    }
1454    TypeScript.preCollectFuncDeclTypes = preCollectFuncDeclTypes;
1455    function preCollectTypes(ast, parent, walker) {
1456        var context = walker.state;
1457        var go = false;
1458        var scopeChain = context.scopeChain;
1459        if (ast.nodeType == NodeType.Script) {
1460            var script = ast;
1461            context.script = script;
1462            go = true;
1463        }
1464        else if (ast.nodeType == NodeType.List) {
1465            go = true;
1466        }
1467        else if (ast.nodeType == NodeType.ImportDeclaration) {
1468            go = preCollectImportTypes(ast, parent, context);
1469        }
1470        else if (ast.nodeType == NodeType.With) {
1471            go = false;
1472        }
1473        else if (ast.nodeType == NodeType.ModuleDeclaration) {
1474            go = preCollectModuleTypes(ast, parent, context);
1475        }
1476        else if (ast.nodeType == NodeType.ClassDeclaration) {
1477            go = preCollectClassTypes(ast, parent, context);
1478        }
1479        else if (ast.nodeType == NodeType.Block) {
1480            go = true;
1481        }
1482        else if (ast.nodeType == NodeType.InterfaceDeclaration) {
1483            go = preCollectInterfaceTypes(ast, parent, context);
1484        }
1485        // This will be a constructor arg because this pass only traverses
1486        // constructor arg lists
1487        else if (ast.nodeType == NodeType.ArgDecl) {
1488            go = preCollectArgDeclTypes(ast, parent, context);
1489        }
1490        else if (ast.nodeType == NodeType.VarDecl) {
1491            go = preCollectVarDeclTypes(ast, parent, context);
1492        }
1493        else if (ast.nodeType == NodeType.FuncDecl) {
1494            go = preCollectFuncDeclTypes(ast, parent, context);
1495        }
1496        else {
1497            if (ast.isStatementOrExpression() && context.scopeChain.moduleDecl) {
1498                context.scopeChain.moduleDecl.recordNonInterface();
1499            }
1500        }
1501        walker.options.goChildren = go;
1502        return ast;
1503    }
1504    TypeScript.preCollectTypes = preCollectTypes;
1505    function postCollectTypes(ast, parent, walker) {
1506        var context = walker.state;
1507        if (ast.nodeType == NodeType.ModuleDeclaration) {
1508            popTypeCollectionScope(context);
1509        }
1510        else if (ast.nodeType == NodeType.ClassDeclaration) {
1511            popTypeCollectionScope(context);
1512        }
1513        else if (ast.nodeType == NodeType.InterfaceDeclaration) {
1514            popTypeCollectionScope(context);
1515        }
1516        return ast;
1517    }
1518    TypeScript.postCollectTypes = postCollectTypes;
1519})(TypeScript || (TypeScript = {}));
1520