• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1//// [parserRealSource9.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 Binder {
9        constructor (public checker: TypeChecker) { }
10        public resolveBaseTypeLinks(typeLinks: TypeLink[], scope: SymbolScope) {
11            var extendsList: Type[] = null;
12            if (typeLinks) {
13                extendsList = new Type[];
14                for (var i = 0, len = typeLinks.length; i < len; i++) {
15                    var typeLink = typeLinks[i];
16                    this.checker.resolvingBases = true;
17                    this.checker.resolveTypeLink(scope, typeLink, true);
18                    this.checker.resolvingBases = false;
19                    if (typeLink.type.isClass()) {
20                        extendsList[i] = typeLink.type.instanceType;
21                    }
22                    else {
23                        extendsList[i] = typeLink.type;
24                    }
25                }
26            }
27            return extendsList;
28        }
29
30        public resolveBases(scope: SymbolScope, type: Type) {
31            type.extendsList = this.resolveBaseTypeLinks(type.extendsTypeLinks, scope);
32
33            var i = 0, len = type.extendsList.length;
34            var derivedIsClass = type.isClassInstance();
35            for (; i < len; i++) {
36                var baseIsClass = type.extendsList[i].isClassInstance();
37                if (type.extendsList[i] != this.checker.anyType) {
38                    if (derivedIsClass) {
39                        if (!baseIsClass) {
40                            this.checker.errorReporter.simpleErrorFromSym(type.symbol,
41                                                                     "A export class may only extend other classes, " + type.extendsList[i].symbol.fullName() + " is an interface.");
42                        }
43                    }
44                    else {
45                        if (baseIsClass) {
46                            this.checker.errorReporter.simpleErrorFromSym(type.symbol,
47                                                                     "An interface may only extend other interfaces, " + type.extendsList[i].symbol.fullName() + " is a class.");
48                        }
49                    }
50                }
51            }
52
53            type.implementsList = this.resolveBaseTypeLinks(type.implementsTypeLinks, scope);
54
55            if (type.implementsList) {
56                for (i = 0, len = type.implementsList.length; i < len; i++) {
57                    var iface = type.implementsList[i];
58                    if (iface.isClassInstance()) {
59                        if (derivedIsClass) {
60                            this.checker.errorReporter.simpleErrorFromSym(type.symbol,
61                                                                     "A class may only implement an interface; " + iface.symbol.fullName() + " is a class.");
62                        }
63                    }
64                }
65            }
66        }
67
68        public resolveSignatureGroup(signatureGroup: SignatureGroup, scope: SymbolScope, instanceType: Type) {
69            var supplyVar = !(signatureGroup.hasImplementation);
70            for (var i = 0, len = signatureGroup.signatures.length; i < len; i++) {
71                var signature = signatureGroup.signatures[i];
72                if (instanceType) {
73                    signature.returnType.type = instanceType;
74                }
75                else {
76                    this.checker.resolveTypeLink(scope, signature.returnType, supplyVar);
77                }
78                var paramLen = signature.parameters.length;
79                for (var j = 0; j < paramLen; j++) {
80                    this.bindSymbol(scope, signature.parameters[j]);
81                }
82                if (signature.hasVariableArgList) {
83                    // check that last parameter has an array type
84                    var lastParam = <ParameterSymbol>signature.parameters[paramLen - 1];
85                    lastParam.argsOffset = paramLen - 1;
86                    if (!lastParam.getType().isArray()) {
87                        this.checker.errorReporter.simpleErrorFromSym(lastParam,
88                                                                 "... parameter must have array type");
89                        lastParam.parameter.typeLink.type = this.checker.makeArrayType(lastParam.parameter.typeLink.type);
90                    }
91                }
92            }
93        }
94
95        public bindType(scope: SymbolScope, type: Type, instanceType: Type): void {
96            if (instanceType) {
97                this.bindType(scope, instanceType, null);
98            }
99            if (type.hasMembers()) {
100                var members = type.members;
101                var ambientMembers = type.ambientMembers;
102                var typeMembers = type.getAllEnclosedTypes(); // REVIEW: Should only be getting exported types?
103                var ambientTypeMembers = type.getAllAmbientEnclosedTypes(); // REVIEW: Should only be getting exported types?
104                var memberScope = new SymbolTableScope(members, ambientMembers, typeMembers, ambientTypeMembers, type.symbol);
105                var agg = new SymbolAggregateScope(type.symbol);
106                var prevCurrentModDecl = this.checker.currentModDecl;
107                var prevBindStatus = this.checker.inBind;
108                agg.addParentScope(memberScope);
109                agg.addParentScope(scope);
110                if (type.isModuleType()) {
111                    this.checker.currentModDecl = <ModuleDeclaration>type.symbol.declAST;
112                    this.checker.inBind = true;
113                }
114                if (members) {
115                    this.bind(agg, type.members.allMembers); // REVIEW: Should only be getting exported types?
116                }
117                if (typeMembers) {
118                    this.bind(agg, typeMembers.allMembers);
119                }
120                if (ambientMembers) {
121                    this.bind(agg, ambientMembers.allMembers);
122                }
123                if (ambientTypeMembers) {
124                    this.bind(agg, ambientTypeMembers.allMembers);
125                }
126                this.checker.currentModDecl = prevCurrentModDecl;
127                this.checker.inBind = prevBindStatus;
128            }
129            if (type.extendsTypeLinks) {
130                this.resolveBases(scope, type);
131            }
132            if (type.construct) {
133                this.resolveSignatureGroup(type.construct, scope, instanceType);
134            }
135            if (type.call) {
136                this.resolveSignatureGroup(type.call, scope, null);
137            }
138            if (type.index) {
139                this.resolveSignatureGroup(type.index, scope, null);
140            }
141            if (type.elementType) {
142                this.bindType(scope, type.elementType, null);
143            }
144        }
145
146        public bindSymbol(scope: SymbolScope, symbol: Symbol) {
147            if (!symbol.bound) {
148                var prevLocationInfo = this.checker.locationInfo;
149                if ((this.checker.units) && (symbol.unitIndex >= 0) && (symbol.unitIndex < this.checker.units.length)) {
150                    this.checker.locationInfo = this.checker.units[symbol.unitIndex];
151                }
152                switch (symbol.kind()) {
153                    case SymbolKind.Type:
154
155                        if (symbol.flags & SymbolFlags.Bound) {
156                            break;
157                        }
158
159                        var typeSymbol = <TypeSymbol>symbol;
160                        typeSymbol.flags |= SymbolFlags.Bound;
161
162                        // Since type collection happens out of order, a dynamic module referenced by an import statement
163                        // may not yet be in scope when the import symbol is created.  In that case, we need to search
164                        // out the module symbol now
165                        // Note that we'll also want to do this in resolveTypeMembers, in case the symbol is set outside the
166                        // context of a given module  (E.g., an outer import statement)
167                        if (typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == NodeType.Name) {
168                            var modPath = (<Identifier>typeSymbol.aliasLink.alias).text;
169                            var modSym = this.checker.findSymbolForDynamicModule(modPath, this.checker.locationInfo.filename, (id) => scope.find(id, false, true));
170                            if (modSym) {
171                                typeSymbol.type = modSym.getType();
172                            }
173                        }
174
175                        if (typeSymbol.type && typeSymbol.type != this.checker.gloModType) {
176                            this.bindType(scope, typeSymbol.type, typeSymbol.instanceType);
177
178                            // bind expansions on the parent type symbol
179                            if (typeSymbol.type.isModuleType()) {
180                                for (var i = 0; i < typeSymbol.expansions.length; i++) {
181                                    this.bindType(scope, typeSymbol.expansions[i], typeSymbol.instanceType);
182                                }
183                            }
184                        }
185                        break;
186                    case SymbolKind.Field:
187                        this.checker.resolveTypeLink(scope, (<FieldSymbol>symbol).field.typeLink,
188                                                false);
189                        break;
190                    case SymbolKind.Parameter:
191                        this.checker.resolveTypeLink(scope,
192                                                (<ParameterSymbol>symbol).parameter.typeLink,
193                                                true);
194                        break;
195                }
196                this.checker.locationInfo = prevLocationInfo;
197            }
198            symbol.bound = true;
199        }
200
201        public bind(scope: SymbolScope, table: IHashTable) {
202            table.map(
203                (key, sym, binder) => {
204                    binder.bindSymbol(scope, sym);
205                },
206                this);
207        }
208    }
209
210}
211
212//// [parserRealSource9.js]
213// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
214// See LICENSE.txt in the project root for complete license information.
215///<reference path='typescript.ts' />
216var TypeScript;
217(function (TypeScript) {
218    var Binder = /** @class */ (function () {
219        function Binder(checker) {
220            this.checker = checker;
221        }
222        Binder.prototype.resolveBaseTypeLinks = function (typeLinks, scope) {
223            var extendsList = null;
224            if (typeLinks) {
225                extendsList = new Type[];
226                for (var i = 0, len = typeLinks.length; i < len; i++) {
227                    var typeLink = typeLinks[i];
228                    this.checker.resolvingBases = true;
229                    this.checker.resolveTypeLink(scope, typeLink, true);
230                    this.checker.resolvingBases = false;
231                    if (typeLink.type.isClass()) {
232                        extendsList[i] = typeLink.type.instanceType;
233                    }
234                    else {
235                        extendsList[i] = typeLink.type;
236                    }
237                }
238            }
239            return extendsList;
240        };
241        Binder.prototype.resolveBases = function (scope, type) {
242            type.extendsList = this.resolveBaseTypeLinks(type.extendsTypeLinks, scope);
243            var i = 0, len = type.extendsList.length;
244            var derivedIsClass = type.isClassInstance();
245            for (; i < len; i++) {
246                var baseIsClass = type.extendsList[i].isClassInstance();
247                if (type.extendsList[i] != this.checker.anyType) {
248                    if (derivedIsClass) {
249                        if (!baseIsClass) {
250                            this.checker.errorReporter.simpleErrorFromSym(type.symbol, "A export class may only extend other classes, " + type.extendsList[i].symbol.fullName() + " is an interface.");
251                        }
252                    }
253                    else {
254                        if (baseIsClass) {
255                            this.checker.errorReporter.simpleErrorFromSym(type.symbol, "An interface may only extend other interfaces, " + type.extendsList[i].symbol.fullName() + " is a class.");
256                        }
257                    }
258                }
259            }
260            type.implementsList = this.resolveBaseTypeLinks(type.implementsTypeLinks, scope);
261            if (type.implementsList) {
262                for (i = 0, len = type.implementsList.length; i < len; i++) {
263                    var iface = type.implementsList[i];
264                    if (iface.isClassInstance()) {
265                        if (derivedIsClass) {
266                            this.checker.errorReporter.simpleErrorFromSym(type.symbol, "A class may only implement an interface; " + iface.symbol.fullName() + " is a class.");
267                        }
268                    }
269                }
270            }
271        };
272        Binder.prototype.resolveSignatureGroup = function (signatureGroup, scope, instanceType) {
273            var supplyVar = !(signatureGroup.hasImplementation);
274            for (var i = 0, len = signatureGroup.signatures.length; i < len; i++) {
275                var signature = signatureGroup.signatures[i];
276                if (instanceType) {
277                    signature.returnType.type = instanceType;
278                }
279                else {
280                    this.checker.resolveTypeLink(scope, signature.returnType, supplyVar);
281                }
282                var paramLen = signature.parameters.length;
283                for (var j = 0; j < paramLen; j++) {
284                    this.bindSymbol(scope, signature.parameters[j]);
285                }
286                if (signature.hasVariableArgList) {
287                    // check that last parameter has an array type
288                    var lastParam = signature.parameters[paramLen - 1];
289                    lastParam.argsOffset = paramLen - 1;
290                    if (!lastParam.getType().isArray()) {
291                        this.checker.errorReporter.simpleErrorFromSym(lastParam, "... parameter must have array type");
292                        lastParam.parameter.typeLink.type = this.checker.makeArrayType(lastParam.parameter.typeLink.type);
293                    }
294                }
295            }
296        };
297        Binder.prototype.bindType = function (scope, type, instanceType) {
298            if (instanceType) {
299                this.bindType(scope, instanceType, null);
300            }
301            if (type.hasMembers()) {
302                var members = type.members;
303                var ambientMembers = type.ambientMembers;
304                var typeMembers = type.getAllEnclosedTypes(); // REVIEW: Should only be getting exported types?
305                var ambientTypeMembers = type.getAllAmbientEnclosedTypes(); // REVIEW: Should only be getting exported types?
306                var memberScope = new SymbolTableScope(members, ambientMembers, typeMembers, ambientTypeMembers, type.symbol);
307                var agg = new SymbolAggregateScope(type.symbol);
308                var prevCurrentModDecl = this.checker.currentModDecl;
309                var prevBindStatus = this.checker.inBind;
310                agg.addParentScope(memberScope);
311                agg.addParentScope(scope);
312                if (type.isModuleType()) {
313                    this.checker.currentModDecl = type.symbol.declAST;
314                    this.checker.inBind = true;
315                }
316                if (members) {
317                    this.bind(agg, type.members.allMembers); // REVIEW: Should only be getting exported types?
318                }
319                if (typeMembers) {
320                    this.bind(agg, typeMembers.allMembers);
321                }
322                if (ambientMembers) {
323                    this.bind(agg, ambientMembers.allMembers);
324                }
325                if (ambientTypeMembers) {
326                    this.bind(agg, ambientTypeMembers.allMembers);
327                }
328                this.checker.currentModDecl = prevCurrentModDecl;
329                this.checker.inBind = prevBindStatus;
330            }
331            if (type.extendsTypeLinks) {
332                this.resolveBases(scope, type);
333            }
334            if (type.construct) {
335                this.resolveSignatureGroup(type.construct, scope, instanceType);
336            }
337            if (type.call) {
338                this.resolveSignatureGroup(type.call, scope, null);
339            }
340            if (type.index) {
341                this.resolveSignatureGroup(type.index, scope, null);
342            }
343            if (type.elementType) {
344                this.bindType(scope, type.elementType, null);
345            }
346        };
347        Binder.prototype.bindSymbol = function (scope, symbol) {
348            if (!symbol.bound) {
349                var prevLocationInfo = this.checker.locationInfo;
350                if ((this.checker.units) && (symbol.unitIndex >= 0) && (symbol.unitIndex < this.checker.units.length)) {
351                    this.checker.locationInfo = this.checker.units[symbol.unitIndex];
352                }
353                switch (symbol.kind()) {
354                    case SymbolKind.Type:
355                        if (symbol.flags & SymbolFlags.Bound) {
356                            break;
357                        }
358                        var typeSymbol = symbol;
359                        typeSymbol.flags |= SymbolFlags.Bound;
360                        // Since type collection happens out of order, a dynamic module referenced by an import statement
361                        // may not yet be in scope when the import symbol is created.  In that case, we need to search
362                        // out the module symbol now
363                        // Note that we'll also want to do this in resolveTypeMembers, in case the symbol is set outside the
364                        // context of a given module  (E.g., an outer import statement)
365                        if (typeSymbol.aliasLink && !typeSymbol.type && typeSymbol.aliasLink.alias.nodeType == NodeType.Name) {
366                            var modPath = typeSymbol.aliasLink.alias.text;
367                            var modSym = this.checker.findSymbolForDynamicModule(modPath, this.checker.locationInfo.filename, function (id) { return scope.find(id, false, true); });
368                            if (modSym) {
369                                typeSymbol.type = modSym.getType();
370                            }
371                        }
372                        if (typeSymbol.type && typeSymbol.type != this.checker.gloModType) {
373                            this.bindType(scope, typeSymbol.type, typeSymbol.instanceType);
374                            // bind expansions on the parent type symbol
375                            if (typeSymbol.type.isModuleType()) {
376                                for (var i = 0; i < typeSymbol.expansions.length; i++) {
377                                    this.bindType(scope, typeSymbol.expansions[i], typeSymbol.instanceType);
378                                }
379                            }
380                        }
381                        break;
382                    case SymbolKind.Field:
383                        this.checker.resolveTypeLink(scope, symbol.field.typeLink, false);
384                        break;
385                    case SymbolKind.Parameter:
386                        this.checker.resolveTypeLink(scope, symbol.parameter.typeLink, true);
387                        break;
388                }
389                this.checker.locationInfo = prevLocationInfo;
390            }
391            symbol.bound = true;
392        };
393        Binder.prototype.bind = function (scope, table) {
394            table.map(function (key, sym, binder) {
395                binder.bindSymbol(scope, sym);
396            }, this);
397        };
398        return Binder;
399    }());
400    TypeScript.Binder = Binder;
401})(TypeScript || (TypeScript = {}));
402