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