| OLD | NEW | 
|---|
| 1 import ts = require('typescript'); | 1 import ts = require('typescript'); | 
| 2 import base = require('./base'); | 2 import base = require('./base'); | 
| 3 import {FacadeConverter} from './facade_converter'; | 3 import {FacadeConverter} from './facade_converter'; | 
| 4 | 4 | 
| 5 /** | 5 /** | 
| 6  * To support arbitrary d.ts files in Dart we often have to merge two TypeScript | 6  * To support arbitrary d.ts files in Dart we often have to merge two TypeScript | 
| 7  * types into a single Dart type because Dart lacks features such as method | 7  * types into a single Dart type because Dart lacks features such as method | 
| 8  * overloads, type aliases, and union types. | 8  * overloads, type aliases, and union types. | 
| 9  */ | 9  */ | 
| 10 export class MergedType { | 10 export class MergedType { | 
| 11   constructor(private fc: FacadeConverter) {} | 11   constructor(private fc: FacadeConverter) {} | 
| 12 | 12 | 
| 13   merge(t?: ts.TypeNode) { | 13   merge(t?: ts.TypeNode) { | 
| 14     if (t) { | 14     if (t) { | 
| 15       // TODO(jacobr): get a better unique name for a type. | 15       // TODO(jacobr): get a better unique name for a type. | 
| 16       switch (t.kind) { | 16       switch (t.kind) { | 
|  | 17         case ts.SyntaxKind.NullKeyword: | 
|  | 18           // No need to include the null type as all Dart types are nullable any
     way. | 
|  | 19           return; | 
| 17         case ts.SyntaxKind.UnionType: | 20         case ts.SyntaxKind.UnionType: | 
| 18           let union = <ts.UnionTypeNode>t; | 21           let union = <ts.UnionTypeNode>t; | 
| 19           union.types.forEach(this.merge.bind(this)); | 22           union.types.forEach(this.merge.bind(this)); | 
| 20           return; | 23           return; | 
| 21         case ts.SyntaxKind.LastTypeNode: | 24         case ts.SyntaxKind.IntersectionType: | 
| 22           this.merge((t as ts.ParenthesizedTypeNode).type); | 25           // Arbitrarily pick the first type of the intersection type as the mer
     ged type. | 
|  | 26           // TODO(jacobr): re-evaluate this logic. | 
|  | 27           let intersection = <ts.IntersectionTypeNode>t; | 
|  | 28           this.merge(intersection.types[0]); | 
| 23           return; | 29           return; | 
| 24         case ts.SyntaxKind.TypePredicate: | 30         case ts.SyntaxKind.TypePredicate: | 
| 25           this.merge((t as ts.TypePredicateNode).type); | 31           this.merge((t as ts.TypePredicateNode).type); | 
| 26           return; | 32           return; | 
| 27         case ts.SyntaxKind.TypeReference: | 33         case ts.SyntaxKind.TypeReference: | 
| 28           // We need to follow Alais types as Dart does not support them for non | 34           // We need to follow Alais types as Dart does not support them for non | 
| 29           // function types. TODO(jacobr): handle them for Function types? | 35           // function types. TODO(jacobr): handle them for Function types? | 
| 30           let typeRef = <ts.TypeReferenceNode>t; | 36           let typeRef = <ts.TypeReferenceNode>t; | 
| 31           let decl = this.fc.getDeclaration(typeRef.typeName); | 37           let decl = this.fc.getDeclaration(typeRef.typeName); | 
| 32           if (decl !== null && decl.kind === ts.SyntaxKind.TypeAliasDeclaration)
      { | 38           if (decl !== null && decl.kind === ts.SyntaxKind.TypeAliasDeclaration)
      { | 
| 33             let alias = <ts.TypeAliasDeclaration>decl; | 39             let alias = <ts.TypeAliasDeclaration>decl; | 
|  | 40             if (!base.supportedAliasType(alias)) { | 
|  | 41               if (typeRef.typeArguments) { | 
|  | 42                 console.log( | 
|  | 43                     'Warning: typeReference with arguements not supported yet:' 
     + t.getText()); | 
|  | 44               } | 
| 34 | 45 | 
| 35             if (typeRef.typeArguments) { | 46               this.merge(alias.type); | 
| 36               throw 'TypeReference with arguements not supported yet:' + t.getTe
     xt(); |  | 
| 37             } | 47             } | 
| 38 |  | 
| 39             this.merge(alias.type); |  | 
| 40             return; | 48             return; | 
| 41           } | 49           } | 
| 42           break; | 50           break; | 
| 43         default: | 51         default: | 
| 44           break; | 52           break; | 
| 45       } | 53       } | 
| 46       this.types[this.fc.generateDartTypeName(t, true)] = t; | 54       this.types[this.fc.generateDartTypeName(t, {insideComment: true})] = t; | 
| 47     } | 55     } | 
| 48   } | 56   } | 
| 49 | 57 | 
| 50   toTypeNode(): ts.TypeNode { | 58   toTypeNode(): ts.TypeNode { | 
| 51     let names = Object.getOwnPropertyNames(this.types); | 59     let names = Object.getOwnPropertyNames(this.types); | 
| 52     if (names.length === 0) { | 60     if (names.length === 0) { | 
| 53       return null; | 61       return null; | 
| 54     } | 62     } | 
| 55     if (names.length === 1) { | 63     if (names.length === 1) { | 
| 56       return this.types[names[0]]; | 64       return this.types[names[0]]; | 
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 102 | 110 | 
| 103   setOptional() { this.optional = true; } | 111   setOptional() { this.optional = true; } | 
| 104 | 112 | 
| 105   private name: {[s: string]: boolean} = {}; | 113   private name: {[s: string]: boolean} = {}; | 
| 106   private type: MergedType; | 114   private type: MergedType; | 
| 107   private optional: boolean = false; | 115   private optional: boolean = false; | 
| 108   private textRange: ts.TextRange; | 116   private textRange: ts.TextRange; | 
| 109 } | 117 } | 
| 110 | 118 | 
| 111 /** | 119 /** | 
|  | 120  * Handle a parameter that is the result of merging parameter declarations from | 
|  | 121  * multiple method overloads. | 
|  | 122  */ | 
|  | 123 export class MergedTypeParameter { | 
|  | 124   constructor(param: ts.TypeParameterDeclaration, fc: FacadeConverter) { | 
|  | 125     this.constraint = new MergedType(fc); | 
|  | 126     this.textRange = param; | 
|  | 127     this.merge(param); | 
|  | 128     this.name = base.ident(param.name); | 
|  | 129   } | 
|  | 130 | 
|  | 131   merge(param: ts.TypeParameterDeclaration) { | 
|  | 132     this.constraint.merge(param.constraint); | 
|  | 133     // We ignore param.expression as it is not supported by Dart. | 
|  | 134   } | 
|  | 135 | 
|  | 136   toTypeParameterDeclaration(): ts.TypeParameterDeclaration { | 
|  | 137     let ret = <ts.TypeParameterDeclaration>ts.createNode(ts.SyntaxKind.TypeParam
     eter); | 
|  | 138     let nameIdentifier = <ts.Identifier>ts.createNode(ts.SyntaxKind.Identifier); | 
|  | 139     nameIdentifier.text = this.name; | 
|  | 140     ret.name = nameIdentifier; | 
|  | 141     base.copyLocation(this.textRange, ret); | 
|  | 142     let constraint = this.constraint.toTypeNode(); | 
|  | 143     // TODO(jacobr): remove this check once we have support for union types with
     in comments. | 
|  | 144     // We can't currently handle union types in merged type parameters as the co
     mments for type | 
|  | 145     // parameters in function types are not there for documentation and impact s
     trong mode. | 
|  | 146     if (constraint && constraint.kind !== ts.SyntaxKind.UnionType) { | 
|  | 147       ret.constraint = constraint; | 
|  | 148     } | 
|  | 149     return ret; | 
|  | 150   } | 
|  | 151 | 
|  | 152   private name: string; | 
|  | 153   private constraint: MergedType; | 
|  | 154   private textRange: ts.TextRange; | 
|  | 155 } | 
|  | 156 | 
|  | 157 /** | 
|  | 158  * Handle a parameter that is the result of merging parameter declarations from | 
|  | 159  * multiple method overloads. | 
|  | 160  */ | 
|  | 161 export class MergedTypeParameters { | 
|  | 162   private mergedParameters: {[s: string]: MergedTypeParameter} = {}; | 
|  | 163   private textRange: ts.TextRange; | 
|  | 164 | 
|  | 165   constructor(private fc: FacadeConverter) {} | 
|  | 166 | 
|  | 167   merge(params: ts.NodeArray<ts.TypeParameterDeclaration>) { | 
|  | 168     if (!params) return; | 
|  | 169     if (!this.textRange) { | 
|  | 170       this.textRange = params; | 
|  | 171     } | 
|  | 172     for (let i = 0; i < params.length; i++) { | 
|  | 173       let param = params[i]; | 
|  | 174       let name = base.ident(param.name); | 
|  | 175       if (Object.hasOwnProperty.call(this.mergedParameters, name)) { | 
|  | 176         let merged = this.mergedParameters[name]; | 
|  | 177         if (merged) { | 
|  | 178           merged.merge(param); | 
|  | 179         } | 
|  | 180       } else { | 
|  | 181         this.mergedParameters[name] = new MergedTypeParameter(param, this.fc); | 
|  | 182       } | 
|  | 183     } | 
|  | 184   } | 
|  | 185 | 
|  | 186   toTypeParameters(): ts.NodeArray<ts.TypeParameterDeclaration> { | 
|  | 187     let names = Object.getOwnPropertyNames(this.mergedParameters); | 
|  | 188     if (names.length === 0) { | 
|  | 189       return undefined; | 
|  | 190     } | 
|  | 191 | 
|  | 192     let ret = [] as ts.NodeArray<ts.TypeParameterDeclaration>; | 
|  | 193     base.copyLocation(this.textRange, ret); | 
|  | 194     for (let i = 0; i < names.length; ++i) { | 
|  | 195       ret.push(this.mergedParameters[names[i]].toTypeParameterDeclaration()); | 
|  | 196     } | 
|  | 197     return ret; | 
|  | 198   } | 
|  | 199 } | 
|  | 200 | 
|  | 201 /** | 
| 112  * Normalize a SourceFile | 202  * Normalize a SourceFile | 
| 113  */ | 203  */ | 
| 114 export function normalizeSourceFile(f: ts.SourceFile) { | 204 export function normalizeSourceFile(f: ts.SourceFile, fc: FacadeConverter) { | 
| 115   let modules: {[name: string]: ts.ModuleDeclaration} = {}; | 205   let modules: {[name: string]: ts.ModuleDeclaration} = {}; | 
| 116 | 206 | 
| 117   // Merge top level modules. | 207   // Merge top level modules. | 
| 118   for (let i = 0; i < f.statements.length; ++i) { | 208   for (let i = 0; i < f.statements.length; ++i) { | 
| 119     let statement = f.statements[i]; | 209     let statement = f.statements[i]; | 
| 120     if (statement.kind !== ts.SyntaxKind.ModuleDeclaration) continue; | 210     if (statement.kind !== ts.SyntaxKind.ModuleDeclaration) continue; | 
| 121     let moduleDecl = <ts.ModuleDeclaration>statement; | 211     let moduleDecl = <ts.ModuleDeclaration>statement; | 
| 122     let name = moduleDecl.name.text; | 212     let name = moduleDecl.name.text; | 
| 123     if (modules.hasOwnProperty(name)) { | 213     if (Object.hasOwnProperty.call(modules, name)) { | 
| 124       let srcBody = modules[name].body; | 214       let srcBody = modules[name].body; | 
| 125       let srcBodyBlock: ts.ModuleBlock; | 215       let srcBodyBlock: ts.ModuleBlock; | 
| 126 | 216 | 
| 127       if (srcBody.kind !== ts.SyntaxKind.ModuleBlock) { | 217       if (srcBody.kind !== ts.SyntaxKind.ModuleBlock) { | 
| 128         throw 'Module body must be a module block.'; | 218         throw 'Module body must be a module block.'; | 
| 129       } | 219       } | 
| 130       srcBodyBlock = <ts.ModuleBlock>srcBody; | 220       srcBodyBlock = <ts.ModuleBlock>srcBody; | 
| 131 | 221 | 
| 132       let body = moduleDecl.body; | 222       let body = moduleDecl.body; | 
| 133       if (body.kind === ts.SyntaxKind.ModuleBlock) { | 223       if (body.kind === ts.SyntaxKind.ModuleBlock) { | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
| 155   } | 245   } | 
| 156 | 246 | 
| 157   function mergeVariablesIntoClasses(n: ts.Node, classes: {[name: string]: base.
     ClassLike}) { | 247   function mergeVariablesIntoClasses(n: ts.Node, classes: {[name: string]: base.
     ClassLike}) { | 
| 158     switch (n.kind) { | 248     switch (n.kind) { | 
| 159       case ts.SyntaxKind.VariableStatement: | 249       case ts.SyntaxKind.VariableStatement: | 
| 160         let statement = <ts.VariableStatement>n; | 250         let statement = <ts.VariableStatement>n; | 
| 161         statement.declarationList.declarations.forEach(function( | 251         statement.declarationList.declarations.forEach(function( | 
| 162             declaration: ts.VariableDeclaration) { | 252             declaration: ts.VariableDeclaration) { | 
| 163           if (declaration.name.kind === ts.SyntaxKind.Identifier) { | 253           if (declaration.name.kind === ts.SyntaxKind.Identifier) { | 
| 164             let name: string = (<ts.Identifier>(declaration.name)).text; | 254             let name: string = (<ts.Identifier>(declaration.name)).text; | 
| 165             if (classes.hasOwnProperty(name)) { | 255             let existingClass = Object.hasOwnProperty.call(classes, name); | 
|  | 256             let hasConstructor = false; | 
|  | 257             if (declaration.type) { | 
|  | 258               let type: ts.TypeNode = declaration.type; | 
|  | 259               if (type.kind === ts.SyntaxKind.TypeLiteral) { | 
|  | 260                 let literal = <ts.TypeLiteralNode>type; | 
|  | 261                 hasConstructor = literal.members.some((member: ts.Node) => { | 
|  | 262                   return member.kind === ts.SyntaxKind.ConstructSignature; | 
|  | 263                 }); | 
|  | 264               } else if (type.kind === ts.SyntaxKind.TypeReference) { | 
|  | 265                 // Handle interfaces with constructors. As Dart does not support
      calling arbitrary | 
|  | 266                 // functions like constructors we need to upgrade the interface 
     to be a class | 
|  | 267                 // so we call invoke the constructor on the interface class. | 
|  | 268                 // Example typescript library definition matching this pattern: | 
|  | 269                 // | 
|  | 270                 // interface XStatic { | 
|  | 271                 //   new (a: string, b): XStatic; | 
|  | 272                 //   foo(); | 
|  | 273                 // } | 
|  | 274                 // | 
|  | 275                 // declare var X: XStatic; | 
|  | 276                 // | 
|  | 277                 // In JavaScript you could just write new X() and create an | 
|  | 278                 // instance of XStatic. We don't | 
|  | 279                 let typeRef = type as ts.TypeReferenceNode; | 
|  | 280                 let typeName = typeRef.typeName; | 
|  | 281                 let symbol = fc.tc.getSymbolAtLocation(typeName); | 
|  | 282                 if (symbol == null) return; | 
|  | 283                 let decl = fc.getSymbolDeclaration(symbol, typeName); | 
|  | 284                 if (decl == null) return; | 
|  | 285                 if (decl.kind !== ts.SyntaxKind.InterfaceDeclaration) return; | 
|  | 286                 let interfaceDecl = decl as base.ExtendedInterfaceDeclaration; | 
|  | 287                 if (!interfaceDecl.members.some( | 
|  | 288                         (member) => { return member.kind === ts.SyntaxKind.Const
     ructSignature; })) | 
|  | 289                   return; | 
|  | 290 | 
|  | 291                 if (interfaceDecl.classLikeVariableDeclaration == null) { | 
|  | 292                   // We could add extra logic to be safer such as only infering 
     that variable names | 
|  | 293                   // are class like for cases where variable names are UpperCame
     lCase matching JS | 
|  | 294                   // conventions that a variable is a Class definition. | 
|  | 295                   interfaceDecl.classLikeVariableDeclaration = declaration; | 
|  | 296                 } | 
|  | 297               } | 
|  | 298             } | 
|  | 299 | 
|  | 300             if (existingClass || hasConstructor) { | 
|  | 301               if (!existingClass) { | 
|  | 302                 // Create a stub existing class to upgrade the object literal to
      if there is not an | 
|  | 303                 // existing class with the same name. | 
|  | 304                 let clazz = <ts.ClassDeclaration>ts.createNode(ts.SyntaxKind.Cla
     ssDeclaration); | 
|  | 305                 base.copyLocation(declaration, clazz); | 
|  | 306                 clazz.name = declaration.name as ts.Identifier; | 
|  | 307                 clazz.members = <ts.NodeArray<ts.ClassElement>>[]; | 
|  | 308                 base.copyLocation(declaration, clazz.members); | 
|  | 309                 replaceNode(n, clazz); | 
|  | 310                 classes[name] = clazz; | 
|  | 311               } | 
|  | 312 | 
| 166               let existing = classes[name]; | 313               let existing = classes[name]; | 
|  | 314               if (existing.kind === ts.SyntaxKind.InterfaceDeclaration) { | 
|  | 315                 let interfaceDecl = existing as base.ExtendedInterfaceDeclaratio
     n; | 
|  | 316                 // It is completely safe to assume that we know the precise clas
     s like variable | 
|  | 317                 // declaration for the interface in this case as they have the s
     ame exact name. | 
|  | 318                 interfaceDecl.classLikeVariableDeclaration = declaration; | 
|  | 319               } | 
| 167               let members = existing.members as Array<ts.ClassElement>; | 320               let members = existing.members as Array<ts.ClassElement>; | 
| 168               if (declaration.type) { | 321               if (declaration.type) { | 
| 169                 let type: ts.TypeNode = declaration.type; | 322                 let type: ts.TypeNode = declaration.type; | 
| 170                 if (type.kind === ts.SyntaxKind.TypeLiteral) { | 323                 if (type.kind === ts.SyntaxKind.TypeLiteral) { | 
| 171                   removeNode(n); | 324                   if (existingClass) { | 
|  | 325                     removeNode(n); | 
|  | 326                   } | 
| 172                   let literal = <ts.TypeLiteralNode>type; | 327                   let literal = <ts.TypeLiteralNode>type; | 
| 173                   literal.members.forEach((member: ts.Node) => { | 328                   literal.members.forEach((member: ts.Node) => { | 
| 174                     switch (member.kind) { | 329                     switch (member.kind) { | 
| 175                       case ts.SyntaxKind.ConstructSignature: | 330                       case ts.SyntaxKind.ConstructSignature: | 
| 176                         let signature: any = member; | 331                         let signature: any = member; | 
| 177                         let constructor = | 332                         let constructor = | 
| 178                             <ts.ConstructorDeclaration>ts.createNode(ts.SyntaxKi
     nd.Constructor); | 333                             <ts.ConstructorDeclaration>ts.createNode(ts.SyntaxKi
     nd.Constructor); | 
| 179                         constructor.parameters = signature.parameters; | 334                         constructor.parameters = signature.parameters; | 
| 180                         constructor.type = signature.type; | 335                         constructor.type = signature.type; | 
| 181                         base.copyLocation(signature, constructor); | 336                         base.copyLocation(signature, constructor); | 
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 242         break; | 397         break; | 
| 243       case ts.SyntaxKind.SourceFile: | 398       case ts.SyntaxKind.SourceFile: | 
| 244         let sourceFile = <ts.SourceFile>parent; | 399         let sourceFile = <ts.SourceFile>parent; | 
| 245         removeFromArray(sourceFile.statements, n); | 400         removeFromArray(sourceFile.statements, n); | 
| 246         break; | 401         break; | 
| 247       default: | 402       default: | 
| 248         throw 'removeNode not implemented for kind:' + parent.kind; | 403         throw 'removeNode not implemented for kind:' + parent.kind; | 
| 249     } | 404     } | 
| 250   } | 405   } | 
| 251 | 406 | 
| 252   function makeCallableClassesImplementFunction(decl: base.ClassLike) { | 407   function replaceInArray(nodes: ts.NodeArray<ts.Node>, v: ts.Node, replacement:
      ts.Node) { | 
| 253     if (base.isCallable(decl)) { | 408     for (let i = 0, len = nodes.length; i < len; ++i) { | 
| 254       // Modify the AST to explicitly state that the class implements Function | 409       if (nodes[i] === v) { | 
| 255       if (!decl.heritageClauses) { | 410         nodes[i] = replacement; | 
| 256         decl.heritageClauses = <ts.NodeArray<ts.HeritageClause>>[]; | 411         break; | 
| 257         base.copyLocation(decl, decl.heritageClauses); |  | 
| 258       } | 412       } | 
| 259       let clauses = decl.heritageClauses; |  | 
| 260       let clause = base.arrayFindPolyfill( |  | 
| 261           clauses, (c) => c.token !== ts.SyntaxKind.ExtendsKeyword || |  | 
| 262               decl.kind === ts.SyntaxKind.InterfaceDeclaration); |  | 
| 263       if (clause == null) { |  | 
| 264         clause = <ts.HeritageClause>ts.createNode(ts.SyntaxKind.HeritageClause); |  | 
| 265         clause.token = decl.kind === ts.SyntaxKind.InterfaceDeclaration ? |  | 
| 266             ts.SyntaxKind.ExtendsKeyword : |  | 
| 267             ts.SyntaxKind.ImplementsKeyword; |  | 
| 268         clause.types = <ts.NodeArray<ts.ExpressionWithTypeArguments>>[]; |  | 
| 269         clause.parent = decl; |  | 
| 270         base.copyLocation(decl, clause); |  | 
| 271         clauses.push(clause); |  | 
| 272       } |  | 
| 273       let functionType = |  | 
| 274           <ts.ExpressionWithTypeArguments>ts.createNode(ts.SyntaxKind.Expression
     WithTypeArguments); |  | 
| 275       functionType.parent = clause; |  | 
| 276       base.copyLocation(clause, functionType); |  | 
| 277       let fn = <ts.Identifier>ts.createNode(ts.SyntaxKind.Identifier); |  | 
| 278       fn.text = 'Function'; |  | 
| 279       fn.parent = functionType; |  | 
| 280       base.copyLocation(functionType, fn); |  | 
| 281       functionType.expression = fn; |  | 
| 282       clause.types.push(functionType); |  | 
| 283     } | 413     } | 
| 284   } | 414   } | 
| 285 | 415 | 
|  | 416   function replaceNode(n: ts.Node, replacement: ts.Node) { | 
|  | 417     let parent = n.parent; | 
|  | 418     replacement.parent = parent; | 
|  | 419     switch (parent.kind) { | 
|  | 420       case ts.SyntaxKind.ModuleBlock: | 
|  | 421         let block = <ts.ModuleBlock>parent; | 
|  | 422         replaceInArray(block.statements, n, replacement); | 
|  | 423         break; | 
|  | 424       case ts.SyntaxKind.SourceFile: | 
|  | 425         let sourceFile = <ts.SourceFile>parent; | 
|  | 426         replaceInArray(sourceFile.statements, n, replacement); | 
|  | 427         break; | 
|  | 428       default: | 
|  | 429         throw 'replaceNode not implemented for kind:' + parent.kind; | 
|  | 430     } | 
|  | 431   } | 
|  | 432 | 
| 286   function gatherClasses(n: ts.Node, classes: {[name: string]: base.ClassLike}) 
     { | 433   function gatherClasses(n: ts.Node, classes: {[name: string]: base.ClassLike}) 
     { | 
| 287     switch (n.kind) { | 434     switch (n.kind) { | 
| 288       case ts.SyntaxKind.ClassDeclaration: | 435       case ts.SyntaxKind.ClassDeclaration: | 
| 289       case ts.SyntaxKind.InterfaceDeclaration: | 436       case ts.SyntaxKind.InterfaceDeclaration: | 
| 290         let classDecl = <base.ClassLike>n; | 437         let classDecl = <base.ClassLike>n; | 
| 291         let name = classDecl.name.text; | 438         let name = classDecl.name.text; | 
| 292         // TODO(jacobr): validate that the classes have consistent | 439         // TODO(jacobr): validate that the classes have consistent | 
| 293         // modifiers, etc. | 440         // modifiers, etc. | 
| 294         if (classes.hasOwnProperty(name)) { | 441         if (Object.hasOwnProperty.call(classes, name)) { | 
| 295           let existing = classes[name]; | 442           let existing = classes[name]; | 
| 296           (classDecl.members as Array<ts.ClassElement>).forEach((e: ts.ClassElem
     ent) => { | 443           (classDecl.members as Array<ts.ClassElement>).forEach((e: ts.ClassElem
     ent) => { | 
| 297             (existing.members as Array<ts.ClassElement>).push(e); | 444             (existing.members as Array<ts.ClassElement>).push(e); | 
| 298             e.parent = existing; | 445             e.parent = existing; | 
| 299           }); | 446           }); | 
| 300           removeNode(classDecl); | 447           removeNode(classDecl); | 
| 301         } else { | 448         } else { | 
| 302           classes[name] = classDecl; | 449           classes[name] = classDecl; | 
| 303           // Perform other class level post processing here. | 450           // Perform other class level post processing here. | 
| 304           makeCallableClassesImplementFunction(classDecl); |  | 
| 305         } | 451         } | 
| 306         break; | 452         break; | 
| 307       case ts.SyntaxKind.ModuleDeclaration: | 453       case ts.SyntaxKind.ModuleDeclaration: | 
| 308       case ts.SyntaxKind.SourceFile: | 454       case ts.SyntaxKind.SourceFile: | 
| 309         let moduleClasses: {[name: string]: base.ClassLike} = {}; | 455         let moduleClasses: {[name: string]: base.ClassLike} = {}; | 
| 310         ts.forEachChild(n, (child) => gatherClasses(child, moduleClasses)); | 456         ts.forEachChild(n, (child) => gatherClasses(child, moduleClasses)); | 
| 311         ts.forEachChild(n, (child) => mergeVariablesIntoClasses(child, moduleCla
     sses)); | 457         ts.forEachChild(n, (child) => mergeVariablesIntoClasses(child, moduleCla
     sses)); | 
| 312 | 458 | 
| 313         break; | 459         break; | 
| 314       case ts.SyntaxKind.ModuleBlock: | 460       case ts.SyntaxKind.ModuleBlock: | 
| 315         ts.forEachChild(n, (child) => gatherClasses(child, classes)); | 461         ts.forEachChild(n, (child) => gatherClasses(child, classes)); | 
| 316         break; | 462         break; | 
| 317       default: | 463       default: | 
| 318         break; | 464         break; | 
| 319     } | 465     } | 
| 320   } | 466   } | 
| 321   gatherClasses(f, {}); | 467   gatherClasses(f, {}); | 
| 322 } | 468 } | 
| OLD | NEW | 
|---|