api-builder: update to dgeni-packages 0.12.0 - factoring out the typescript package
This commit is contained in:
		
							parent
							
								
									aaa927bc43
								
							
						
					
					
						commit
						ac583748d1
					
				| @ -34,7 +34,7 @@ | |||||||
|     "codelyzer": "0.0.18", |     "codelyzer": "0.0.18", | ||||||
|     "del": "^1.2.0", |     "del": "^1.2.0", | ||||||
|     "dgeni": "^0.4.0", |     "dgeni": "^0.4.0", | ||||||
|     "dgeni-packages": "^0.11.1", |     "dgeni-packages": "^0.12.0", | ||||||
|     "diff": "^2.1.3", |     "diff": "^2.1.3", | ||||||
|     "fs-extra": "^0.24.0", |     "fs-extra": "^0.24.0", | ||||||
|     "glob": "^5.0.14", |     "glob": "^5.0.14", | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| var Package = require('dgeni').Package; | var Package = require('dgeni').Package; | ||||||
| var jsdocPackage = require('dgeni-packages/jsdoc'); | var jsdocPackage = require('dgeni-packages/jsdoc'); | ||||||
| var nunjucksPackage = require('dgeni-packages/nunjucks'); | var nunjucksPackage = require('dgeni-packages/nunjucks'); | ||||||
| var typescriptPackage = require('../typescript-package'); | var typescriptPackage = require('dgeni-packages/typescript'); | ||||||
| var linksPackage = require('../links-package'); | var linksPackage = require('../links-package'); | ||||||
| var gitPackage = require('dgeni-packages/git'); | var gitPackage = require('dgeni-packages/git'); | ||||||
| var path = require('canonical-path'); | var path = require('canonical-path'); | ||||||
|  | |||||||
| @ -1,73 +0,0 @@ | |||||||
| var basePackage = require('dgeni-packages/base'); |  | ||||||
| var Package = require('dgeni').Package; |  | ||||||
| var path = require('canonical-path'); |  | ||||||
| 
 |  | ||||||
| // Define the dgeni package for generating the docs
 |  | ||||||
| module.exports = new Package('typescript-parsing', [basePackage]) |  | ||||||
| 
 |  | ||||||
| // Register the services and file readers
 |  | ||||||
| .factory(require('./services/modules')) |  | ||||||
| .factory(require('./services/tsParser')) |  | ||||||
| .factory(require('./services/tsParser/createCompilerHost')) |  | ||||||
| .factory(require('./services/tsParser/getFileInfo')) |  | ||||||
| .factory(require('./services/tsParser/getExportDocType')) |  | ||||||
| .factory(require('./services/tsParser/getContent')) |  | ||||||
| 
 |  | ||||||
| .factory(require('./services/convertPrivateClassesToInterfaces')) |  | ||||||
| 
 |  | ||||||
| .factory('EXPORT_DOC_TYPES', function() { |  | ||||||
|   return [ |  | ||||||
|     'class', |  | ||||||
|     'interface', |  | ||||||
|     'function', |  | ||||||
|     'var', |  | ||||||
|     'const', |  | ||||||
|     'let', |  | ||||||
|     'enum', |  | ||||||
|     'type-alias' |  | ||||||
|   ]; |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // Register the processors
 |  | ||||||
| .processor(require('./processors/readTypeScriptModules')) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // Configure the log service
 |  | ||||||
| .config(function(log) { |  | ||||||
|   log.level = 'warn'; |  | ||||||
| }) |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // Configure ids and paths
 |  | ||||||
| .config(function(computeIdsProcessor, computePathsProcessor, EXPORT_DOC_TYPES) { |  | ||||||
| 
 |  | ||||||
|   computeIdsProcessor.idTemplates.push({ |  | ||||||
|     docTypes: ['member'], |  | ||||||
|     idTemplate: '${classDoc.id}.${name}', |  | ||||||
|     getAliases: function(doc) { |  | ||||||
|       return doc.classDoc.aliases.map(function(alias) { return alias + '.' + doc.name; }); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   computePathsProcessor.pathTemplates.push({ |  | ||||||
|     docTypes: ['member'], |  | ||||||
|     pathTemplate: '${classDoc.path}#${name}', |  | ||||||
|     getOutputPath: function() {} // These docs are not written to their own file, instead they are part of their class doc
 |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   var MODULES_DOCS_PATH = 'partials/modules'; |  | ||||||
| 
 |  | ||||||
|   computePathsProcessor.pathTemplates.push({ |  | ||||||
|     docTypes: ['module'], |  | ||||||
|     pathTemplate: '/${id}', |  | ||||||
|     outputPathTemplate: MODULES_DOCS_PATH + '/${id}/index.html' |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   computePathsProcessor.pathTemplates.push({ |  | ||||||
|     docTypes: EXPORT_DOC_TYPES, |  | ||||||
|     pathTemplate: '${moduleDoc.path}/${name}', |  | ||||||
|     outputPathTemplate: MODULES_DOCS_PATH + '/${path}/index.html' |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
| @ -1,11 +0,0 @@ | |||||||
| var Package = require('dgeni').Package; |  | ||||||
| 
 |  | ||||||
| module.exports = function mockPackage() { |  | ||||||
| 
 |  | ||||||
|   return new Package('mockPackage', [require('../')]) |  | ||||||
| 
 |  | ||||||
|   // provide a mock log service
 |  | ||||||
|   .factory('log', function() { return require('dgeni/lib/mocks/log')(false); }) |  | ||||||
|   .factory('templateEngine', function() { return {}; }); |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| @ -1,4 +0,0 @@ | |||||||
| export var __esModule = true; |  | ||||||
| export class OKToExport {} |  | ||||||
| export function _thisIsPrivate() {} |  | ||||||
| export var thisIsOK = '!'; |  | ||||||
| @ -1,5 +0,0 @@ | |||||||
| export interface MyInterface { |  | ||||||
|   optionalProperty? : string |  | ||||||
|   <T, U extends Findable<T>>(param: T) : U |  | ||||||
|   new (param: number) : MyInterface |  | ||||||
| } |  | ||||||
| @ -1,6 +0,0 @@ | |||||||
| export class Test { |  | ||||||
|   firstItem; |  | ||||||
|   constructor() { this.doStuff(); } |  | ||||||
|   otherMethod() {} |  | ||||||
|   doStuff() {} |  | ||||||
| } |  | ||||||
| @ -1 +0,0 @@ | |||||||
| export var x = 10; |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| export { x as y} from './privateModule'; |  | ||||||
| 
 |  | ||||||
| export abstract class AbstractClass {} |  | ||||||
| @ -1 +0,0 @@ | |||||||
| export var x = 100; |  | ||||||
| @ -1,34 +0,0 @@ | |||||||
| /** |  | ||||||
|  * @module |  | ||||||
|  * @description |  | ||||||
|  * This is the module description |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| export * from 'importedSrc'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * This is some random other comment |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * This is MyClass |  | ||||||
|  */ |  | ||||||
| export class MyClass { |  | ||||||
|   message: String; |  | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * Create a new MyClass |  | ||||||
|    * @param {String} name The name to say hello to |  | ||||||
|    */ |  | ||||||
|   constructor(name) { this.message = 'hello ' + name; } |  | ||||||
| 
 |  | ||||||
|   /** |  | ||||||
|    * Return a greeting message |  | ||||||
|    */ |  | ||||||
|   greet() { return this.message; } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * An exported function |  | ||||||
|  */ |  | ||||||
| export var myFn = (val: number) => return val * 2; |  | ||||||
| @ -1,451 +0,0 @@ | |||||||
| var glob = require('glob'); |  | ||||||
| var path = require('canonical-path'); |  | ||||||
| var _ = require('lodash'); |  | ||||||
| var ts = require('typescript'); |  | ||||||
| 
 |  | ||||||
| module.exports = function readTypeScriptModules(tsParser, modules, getFileInfo, |  | ||||||
|                                                 getExportDocType, getContent, createDocMessage, log) { |  | ||||||
| 
 |  | ||||||
|   return { |  | ||||||
|     $runAfter: ['files-read'], |  | ||||||
|     $runBefore: ['parsing-tags'], |  | ||||||
| 
 |  | ||||||
|     $validate: { |  | ||||||
|       sourceFiles: {presence: true}, |  | ||||||
|       basePath: {presence: true}, |  | ||||||
|       hidePrivateMembers: {inclusion: [true, false]}, |  | ||||||
|       sortClassMembers: {inclusion: [true, false]}, |  | ||||||
|       ignoreExportsMatching: {} |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     // A collection of globs that identify those modules for which we should create docs
 |  | ||||||
|     sourceFiles: [], |  | ||||||
|     // The base path from which to load the source files
 |  | ||||||
|     basePath: '.', |  | ||||||
|     // We can ignore members of classes that are private
 |  | ||||||
|     hidePrivateMembers: true, |  | ||||||
|     // We leave class members sorted in order of declaration
 |  | ||||||
|     sortClassMembers: false, |  | ||||||
|     // We can provide a collection of strings or regexes to ignore exports whose export names match
 |  | ||||||
|     ignoreExportsMatching: ['___esModule', '___core_private_types__', '___platform_browser_private__', '___compiler_private__', '__core_private__', '___core_private__'], |  | ||||||
| 
 |  | ||||||
|     $process: function(docs) { |  | ||||||
| 
 |  | ||||||
|       // Convert ignoreExportsMatching to an array of regexes
 |  | ||||||
|       var ignoreExportsMatching = convertToRegexCollection(this.ignoreExportsMatching); |  | ||||||
| 
 |  | ||||||
|       var hidePrivateMembers = this.hidePrivateMembers; |  | ||||||
|       var sortClassMembers = this.sortClassMembers; |  | ||||||
| 
 |  | ||||||
|       var basePath = path.resolve(this.basePath); |  | ||||||
|       var filesPaths = expandSourceFiles(this.sourceFiles, basePath); |  | ||||||
|       var parseInfo = tsParser.parse(filesPaths, this.basePath); |  | ||||||
|       var moduleSymbols = parseInfo.moduleSymbols; |  | ||||||
| 
 |  | ||||||
|       // Iterate through each of the modules that were parsed and generate a module doc
 |  | ||||||
|       // as well as docs for each module's exports.
 |  | ||||||
|       moduleSymbols.forEach(function(moduleSymbol) { |  | ||||||
| 
 |  | ||||||
|         var moduleDoc = createModuleDoc(moduleSymbol, basePath); |  | ||||||
| 
 |  | ||||||
|         // Add this module doc to the module lookup collection and the docs collection
 |  | ||||||
|         modules[moduleDoc.id] = moduleDoc; |  | ||||||
|         docs.push(moduleDoc); |  | ||||||
| 
 |  | ||||||
|         // Iterate through this module's exports and generate a doc for each
 |  | ||||||
|         moduleSymbol.exportArray.forEach(function(exportSymbol) { |  | ||||||
| 
 |  | ||||||
|           // Ignore exports starting with an underscore
 |  | ||||||
|           if (anyMatches(ignoreExportsMatching, exportSymbol.name)) return; |  | ||||||
| 
 |  | ||||||
|           // If the symbol is an Alias then for most things we want the original resolved symbol
 |  | ||||||
|           var resolvedExport = exportSymbol.resolvedSymbol || exportSymbol; |  | ||||||
| 
 |  | ||||||
|           // If the resolved symbol contains no declarations then it is invalid
 |  | ||||||
|           // (probably an abstract class)
 |  | ||||||
|           // For the moment we are just going to ignore such exports
 |  | ||||||
|           // TODO: find a way of generating docs for them
 |  | ||||||
|           if (!resolvedExport.declarations) return; |  | ||||||
| 
 |  | ||||||
|           var exportDoc = createExportDoc(exportSymbol.name, resolvedExport, moduleDoc, basePath, parseInfo.typeChecker); |  | ||||||
|           log.debug('>>>> EXPORT: ' + exportDoc.name + ' (' + exportDoc.docType + ') from ' + moduleDoc.id); |  | ||||||
| 
 |  | ||||||
|           // Add this export doc to its module doc
 |  | ||||||
|           moduleDoc.exports.push(exportDoc); |  | ||||||
|           docs.push(exportDoc); |  | ||||||
| 
 |  | ||||||
|           exportDoc.members = []; |  | ||||||
|           exportDoc.statics = []; |  | ||||||
| 
 |  | ||||||
|           // Generate docs for each of the export's members
 |  | ||||||
|           if (resolvedExport.flags & ts.SymbolFlags.HasMembers) { |  | ||||||
| 
 |  | ||||||
|             for(var memberName in resolvedExport.members) { |  | ||||||
|               // FIXME(alexeagle): why do generic type params appear in members?
 |  | ||||||
|               if (memberName === 'T') { |  | ||||||
|                 continue; |  | ||||||
|               } |  | ||||||
|               log.silly('>>>>>> member: ' + memberName + ' from ' + exportDoc.id + ' in ' + moduleDoc.id); |  | ||||||
|               var memberSymbol = resolvedExport.members[memberName]; |  | ||||||
|               var memberDoc = createMemberDoc(memberSymbol, exportDoc, basePath, parseInfo.typeChecker); |  | ||||||
| 
 |  | ||||||
|               // We special case the constructor and sort the other members alphabetically
 |  | ||||||
|               if (memberSymbol.flags & ts.SymbolFlags.Constructor) { |  | ||||||
|                 exportDoc.constructorDoc = memberDoc; |  | ||||||
|                 docs.push(memberDoc); |  | ||||||
|               } else if (!hidePrivateMembers || memberSymbol.name.charAt(0) !== '_') { |  | ||||||
|                 docs.push(memberDoc); |  | ||||||
|                 exportDoc.members.push(memberDoc); |  | ||||||
|               } else if (memberSymbol.name === '__call' && memberSymbol.flags & ts.SymbolFlags.Signature) { |  | ||||||
|                 docs.push(memberDoc); |  | ||||||
|                 exportDoc.callMember = memberDoc; |  | ||||||
|               } else if (memberSymbol.name === '__new' && memberSymbol.flags & ts.SymbolFlags.Signature) { |  | ||||||
|                 docs.push(memberDoc); |  | ||||||
|                 exportDoc.newMember = memberDoc; |  | ||||||
|               } |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           if (exportDoc.docType === 'enum') { |  | ||||||
|             for(var memberName in resolvedExport.exports) { |  | ||||||
|               log.silly('>>>>>> member: ' + memberName + ' from ' + exportDoc.id + ' in ' + moduleDoc.id); |  | ||||||
|               var memberSymbol = resolvedExport.exports[memberName]; |  | ||||||
|               var memberDoc = createMemberDoc(memberSymbol, exportDoc, basePath, parseInfo.typeChecker); |  | ||||||
|               docs.push(memberDoc); |  | ||||||
|               exportDoc.members.push(memberDoc); |  | ||||||
|             } |  | ||||||
|           } else if (resolvedExport.flags & ts.SymbolFlags.HasExports) { |  | ||||||
|             for (var exported in resolvedExport.exports) { |  | ||||||
|               if (exported === 'prototype') continue; |  | ||||||
|               if (hidePrivateMembers && exported.charAt(0) === '_') continue; |  | ||||||
|               var memberSymbol = resolvedExport.exports[exported]; |  | ||||||
|               var memberDoc = createMemberDoc(memberSymbol, exportDoc, basePath, parseInfo.typeChecker); |  | ||||||
|               memberDoc.isStatic = true; |  | ||||||
|               docs.push(memberDoc); |  | ||||||
|               exportDoc.statics.push(memberDoc); |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           if (sortClassMembers) { |  | ||||||
|             exportDoc.members.sort(function(a, b) { |  | ||||||
|               if (a.name > b.name) return 1; |  | ||||||
|               if (a.name < b.name) return -1; |  | ||||||
|               return 0; |  | ||||||
|             }); |  | ||||||
|             exportDoc.statics.sort(function(a, b) { |  | ||||||
|               if (a.name > b.name) return 1; |  | ||||||
|               if (a.name < b.name) return -1; |  | ||||||
|               return 0; |  | ||||||
|             }); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   function createModuleDoc(moduleSymbol, basePath) { |  | ||||||
|     var id = moduleSymbol.name.replace(/^"|"$/g, ''); |  | ||||||
|     var name = id.split('/').pop(); |  | ||||||
|     var moduleDoc = { |  | ||||||
|       docType: 'module', |  | ||||||
|       name: name, |  | ||||||
|       id: id, |  | ||||||
|       aliases: [id, name], |  | ||||||
|       moduleTree: moduleSymbol, |  | ||||||
|       content: getContent(moduleSymbol), |  | ||||||
|       exports: [], |  | ||||||
|       fileInfo: getFileInfo(moduleSymbol, basePath), |  | ||||||
|       location: getLocation(moduleSymbol) |  | ||||||
|     }; |  | ||||||
|     return moduleDoc; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function createExportDoc(name, exportSymbol, moduleDoc, basePath, typeChecker) { |  | ||||||
|     var typeParamString = ''; |  | ||||||
|     var heritageString = ''; |  | ||||||
|     var typeDefinition = ''; |  | ||||||
| 
 |  | ||||||
|     exportSymbol.declarations.forEach(function(decl) { |  | ||||||
|       var sourceFile = ts.getSourceFileOfNode(decl); |  | ||||||
| 
 |  | ||||||
|       if (decl.typeParameters) { |  | ||||||
|         typeParamString = '<' + getText(sourceFile, decl.typeParameters) + '>'; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (decl.symbol.flags & ts.SymbolFlags.TypeAlias) { |  | ||||||
|         typeDefinition = getText(sourceFile, decl.type); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       if (decl.heritageClauses) { |  | ||||||
|         decl.heritageClauses.forEach(function(heritage) { |  | ||||||
| 
 |  | ||||||
|           if (heritage.token == ts.SyntaxKind.ExtendsKeyword) { |  | ||||||
|             heritageString += " extends"; |  | ||||||
|             heritage.types.forEach(function(typ, idx) { |  | ||||||
|               heritageString += (idx > 0 ? ',' : '') + typ.getFullText(); |  | ||||||
|             }); |  | ||||||
|           } |  | ||||||
| 
 |  | ||||||
|           if (heritage.token == ts.SyntaxKind.ImplementsKeyword) { |  | ||||||
|             heritageString += " implements"; |  | ||||||
|             heritage.types.forEach(function(typ, idx) { |  | ||||||
|               heritageString += (idx > 0 ? ', ' : '') + typ.getFullText(); |  | ||||||
|             }); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     //Make sure duplicate aliases aren't created, so "Ambiguous link" warnings are prevented
 |  | ||||||
|     var aliasNames = [name, moduleDoc.id + '/' + name]; |  | ||||||
|     if (typeParamString) { |  | ||||||
|       aliasNames.push(name + typeParamString); |  | ||||||
|       aliasNames.push(moduleDoc.id + '/' + name + typeParamString); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     var exportDoc = { |  | ||||||
|       docType: getExportDocType(exportSymbol), |  | ||||||
|       exportSymbol: exportSymbol, |  | ||||||
|       name: name, |  | ||||||
|       id: moduleDoc.id + '/' + name, |  | ||||||
|       typeParams: typeParamString, |  | ||||||
|       heritage: heritageString, |  | ||||||
|       decorators: getDecorators(exportSymbol), |  | ||||||
|       aliases: aliasNames, |  | ||||||
|       moduleDoc: moduleDoc, |  | ||||||
|       content: getContent(exportSymbol), |  | ||||||
|       fileInfo: getFileInfo(exportSymbol, basePath), |  | ||||||
|       location: getLocation(exportSymbol) |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     if (exportDoc.docType === 'var' || exportDoc.docType === 'const' || exportDoc.docType === 'let') { |  | ||||||
|       exportDoc.symbolTypeName = exportSymbol.valueDeclaration.type && |  | ||||||
|                                  exportSymbol.valueDeclaration.type.typeName && |  | ||||||
|                                  exportSymbol.valueDeclaration.type.typeName.text; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (exportDoc.docType === 'type-alias') { |  | ||||||
|       exportDoc.returnType = getReturnType(typeChecker, exportSymbol); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(exportSymbol.flags & ts.SymbolFlags.Function) { |  | ||||||
|       exportDoc.parameters = getParameters(typeChecker, exportSymbol); |  | ||||||
|     } |  | ||||||
|     if(exportSymbol.flags & ts.SymbolFlags.Value) { |  | ||||||
|       exportDoc.returnType = getReturnType(typeChecker, exportSymbol); |  | ||||||
|     } |  | ||||||
|     if (exportSymbol.flags & ts.SymbolFlags.TypeAlias) { |  | ||||||
|       exportDoc.typeDefinition = typeDefinition; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // Compute the original module name from the relative file path
 |  | ||||||
|     exportDoc.originalModule = exportDoc.fileInfo.relativePath |  | ||||||
|         .replace(new RegExp('\.' + exportDoc.fileInfo.extension + '$'), ''); |  | ||||||
| 
 |  | ||||||
|     return exportDoc; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function createMemberDoc(memberSymbol, classDoc, basePath, typeChecker) { |  | ||||||
|     var memberDoc = { |  | ||||||
|       docType: 'member', |  | ||||||
|       classDoc: classDoc, |  | ||||||
|       name: memberSymbol.name, |  | ||||||
|       decorators: getDecorators(memberSymbol), |  | ||||||
|       content: getContent(memberSymbol), |  | ||||||
|       fileInfo: getFileInfo(memberSymbol, basePath), |  | ||||||
|       location: getLocation(memberSymbol) |  | ||||||
|     }; |  | ||||||
| 
 |  | ||||||
|     memberDoc.typeParameters = getTypeParameters(typeChecker, memberSymbol); |  | ||||||
| 
 |  | ||||||
|     if(memberSymbol.flags & (ts.SymbolFlags.Signature) ) { |  | ||||||
|       memberDoc.parameters = getParameters(typeChecker, memberSymbol); |  | ||||||
|       memberDoc.returnType = getReturnType(typeChecker, memberSymbol); |  | ||||||
|       switch(memberDoc.name) { |  | ||||||
|         case '__call': |  | ||||||
|           memberDoc.name = ''; |  | ||||||
|           break; |  | ||||||
|         case '__new': |  | ||||||
|           memberDoc.name = 'new'; |  | ||||||
|           break; |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (memberSymbol.flags & ts.SymbolFlags.Method) { |  | ||||||
|       // NOTE: we use the property name `parameters` here so we don't conflict
 |  | ||||||
|       // with the `params` property that will be updated by dgeni reading the
 |  | ||||||
|       // `@param` tags from the docs
 |  | ||||||
|       memberDoc.parameters = getParameters(typeChecker, memberSymbol); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if (memberSymbol.flags & ts.SymbolFlags.Constructor) { |  | ||||||
|       memberDoc.parameters = getParameters(typeChecker, memberSymbol); |  | ||||||
|       memberDoc.name = 'constructor'; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(memberSymbol.flags & ts.SymbolFlags.Value) { |  | ||||||
|       memberDoc.returnType = getReturnType(typeChecker, memberSymbol); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     if(memberSymbol.flags & ts.SymbolFlags.Optional) { |  | ||||||
|       memberDoc.optional = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return memberDoc; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   function getDecorators(symbol) { |  | ||||||
| 
 |  | ||||||
|     var declaration = symbol.valueDeclaration || symbol.declarations[0]; |  | ||||||
|     var sourceFile = ts.getSourceFileOfNode(declaration); |  | ||||||
| 
 |  | ||||||
|     var decorators = declaration.decorators && declaration.decorators.map(function(decorator) { |  | ||||||
|       decorator = decorator.expression; |  | ||||||
|       return { |  | ||||||
|         name: decorator.expression ? decorator.expression.text : decorator.text, |  | ||||||
|         arguments: decorator.arguments && decorator.arguments.map(function(argument) { |  | ||||||
|           return getText(sourceFile, argument).trim(); |  | ||||||
|         }), |  | ||||||
|         argumentInfo: decorator.arguments && decorator.arguments.map(function(argument) { |  | ||||||
|           return parseArgument(argument); |  | ||||||
|         }), |  | ||||||
|         expression: decorator |  | ||||||
|       }; |  | ||||||
|     }); |  | ||||||
|     return decorators; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function parseProperties(properties) { |  | ||||||
|     var result = {}; |  | ||||||
|     _.forEach(properties, function(property) { |  | ||||||
|       result[property.name.text] = parseArgument(property.initializer); |  | ||||||
|     }); |  | ||||||
|     return result; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function parseArgument(argument) { |  | ||||||
|     if (argument.text) return argument.text; |  | ||||||
|     if (argument.properties) return parseProperties(argument.properties); |  | ||||||
|     if (argument.elements) return argument.elements.map(function(element) { return element.text; }); |  | ||||||
|     var sourceFile = ts.getSourceFileOfNode(argument); |  | ||||||
|     var text = getText(sourceFile, argument).trim(); |  | ||||||
|     return text; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function getParameters(typeChecker, symbol) { |  | ||||||
|     var declaration = symbol.valueDeclaration || symbol.declarations[0]; |  | ||||||
|     var sourceFile = ts.getSourceFileOfNode(declaration); |  | ||||||
|     if (!declaration.parameters) { |  | ||||||
|       var location = getLocation(symbol); |  | ||||||
|       throw new Error('missing declaration parameters for "' + symbol.name + |  | ||||||
|         '" in ' + sourceFile.fileName + |  | ||||||
|         ' at line ' + location.start.line); |  | ||||||
|     } |  | ||||||
|     return declaration.parameters.map(function(parameter) { |  | ||||||
|       var paramText = ''; |  | ||||||
|       if (parameter.dotDotDotToken) { |  | ||||||
|         paramText += '...'; |  | ||||||
|       } |  | ||||||
|       paramText += getText(sourceFile, parameter.name); |  | ||||||
|       if (parameter.questionToken || parameter.initializer) { |  | ||||||
|         paramText += '?'; |  | ||||||
|       } |  | ||||||
|       if (parameter.type) { |  | ||||||
|         paramText += ':' + getType(sourceFile, parameter.type); |  | ||||||
|       } else { |  | ||||||
|         paramText += ': any'; |  | ||||||
|         if (parameter.dotDotDotToken) { |  | ||||||
|           paramText += '[]'; |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       return paramText.trim(); |  | ||||||
|     }); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function getTypeParameters(typeChecker, symbol) { |  | ||||||
|     var declaration = symbol.valueDeclaration || symbol.declarations[0]; |  | ||||||
|     var sourceFile = ts.getSourceFileOfNode(declaration); |  | ||||||
|     if (!declaration.typeParameters) return; |  | ||||||
|     var typeParams = declaration.typeParameters.map(function(type) { |  | ||||||
|       return getText(sourceFile, type).trim(); |  | ||||||
|     }); |  | ||||||
|     return typeParams; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function getReturnType(typeChecker, symbol) { |  | ||||||
|     var declaration = symbol.valueDeclaration || symbol.declarations[0]; |  | ||||||
|     var sourceFile = ts.getSourceFileOfNode(declaration); |  | ||||||
|     if (declaration.type) { |  | ||||||
|       return getType(sourceFile, declaration.type).trim(); |  | ||||||
|     } else if (declaration.initializer) { |  | ||||||
|       // The symbol does not have a "type" but it is being initialized
 |  | ||||||
|       // so we can deduce the type of from the initializer (mostly).
 |  | ||||||
|       if (declaration.initializer.expression) { |  | ||||||
|         return declaration.initializer.expression.text.trim(); |  | ||||||
|       } else { |  | ||||||
|         return getType(sourceFile, declaration.initializer).trim(); |  | ||||||
|       } |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   function expandSourceFiles(sourceFiles, basePath) { |  | ||||||
|     var filePaths = []; |  | ||||||
|     sourceFiles.forEach(function(sourcePattern) { |  | ||||||
|       filePaths = filePaths.concat(glob.sync(sourcePattern, { cwd: basePath })); |  | ||||||
|     }); |  | ||||||
|     return filePaths; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   function getText(sourceFile, node) { |  | ||||||
|     return sourceFile.text.substring(node.pos, node.end); |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // Strip any local renamed imports from the front of types
 |  | ||||||
|   function getType(sourceFile, type) { |  | ||||||
|     var text = getText(sourceFile, type); |  | ||||||
|     while (text.indexOf(".") >= 0) { |  | ||||||
|       // Keep namespaced symbols in RxNext
 |  | ||||||
|       if (text.match(/^\s*RxNext\./)) break; |  | ||||||
|       // handle the case List<thing.stuff> -> List<stuff>
 |  | ||||||
|       text = text.replace(/([^.<]*)\.([^>]*)/, "$2"); |  | ||||||
|     } |  | ||||||
|     return text; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   function getLocation(symbol) { |  | ||||||
|     var node = symbol.valueDeclaration || symbol.declarations[0]; |  | ||||||
|     var sourceFile = ts.getSourceFileOfNode(node); |  | ||||||
|     var location = { |  | ||||||
|       start: ts.getLineAndCharacterOfPosition(sourceFile, node.pos), |  | ||||||
|       end: ts.getLineAndCharacterOfPosition(sourceFile, node.end) |  | ||||||
|     }; |  | ||||||
|     return location; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| function convertToRegexCollection(items) { |  | ||||||
|   if (!items) return []; |  | ||||||
| 
 |  | ||||||
|   // Must be an array
 |  | ||||||
|   if (!_.isArray(items)) { |  | ||||||
|     items = [items]; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
|   // Convert string to exact matching regexes
 |  | ||||||
|   return items.map(function(item) { |  | ||||||
|     return _.isString(item) ? new RegExp('^' + item + '$') : item; |  | ||||||
|   }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| function anyMatches(regexes, item) { |  | ||||||
|   for(var i=0; i<regexes.length; ++i) { |  | ||||||
|     if ( item.match(regexes[i]) ) return true; |  | ||||||
|   } |  | ||||||
|   return false; |  | ||||||
| } |  | ||||||
| @ -1,136 +0,0 @@ | |||||||
| var mockPackage = require('../mocks/mockPackage'); |  | ||||||
| var Dgeni = require('dgeni'); |  | ||||||
| var path = require('canonical-path'); |  | ||||||
| var _ = require('lodash'); |  | ||||||
| 
 |  | ||||||
| describe('readTypeScriptModules', function() { |  | ||||||
|   var dgeni, injector, processor; |  | ||||||
| 
 |  | ||||||
|   beforeEach(function() { |  | ||||||
|     dgeni = new Dgeni([mockPackage()]); |  | ||||||
|     injector = dgeni.configureInjector(); |  | ||||||
|     processor = injector.get('readTypeScriptModules'); |  | ||||||
|     processor.basePath = path.resolve(__dirname, '../mocks/readTypeScriptModules'); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   describe('exportDocs', function() { |  | ||||||
|     it('should provide the original module if the export is re-exported', function() { |  | ||||||
|       processor.sourceFiles = [ 'publicModule.ts' ]; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
| 
 |  | ||||||
|       var exportedDoc = docs[1]; |  | ||||||
|       expect(exportedDoc.originalModule).toEqual('privateModule'); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should include exported abstract classes', function() { |  | ||||||
|       processor.sourceFiles = [ 'publicModule.ts' ]; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
| 
 |  | ||||||
|       var exportedDoc = docs[2]; |  | ||||||
|       expect(exportedDoc.name).toEqual('AbstractClass'); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('ignoreExportsMatching', function() { |  | ||||||
|     it('should ignore exports that match items in the `ignoreExportsMatching` property', function() { |  | ||||||
|       processor.sourceFiles = [ 'ignoreExportsMatching.ts']; |  | ||||||
|       processor.ignoreExportsMatching = [/^_/]; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
| 
 |  | ||||||
|       var moduleDoc = docs[0]; |  | ||||||
|       expect(moduleDoc.docType).toEqual('module'); |  | ||||||
|       expect(moduleDoc.exports).toEqual([ |  | ||||||
|         jasmine.objectContaining({ name: 'OKToExport' }), |  | ||||||
|         jasmine.objectContaining({ name: 'thisIsOK' }) |  | ||||||
|       ]); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should only ignore `___esModule` exports by default', function() { |  | ||||||
|       processor.sourceFiles = [ 'ignoreExportsMatching.ts']; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
| 
 |  | ||||||
|       var moduleDoc = docs[0]; |  | ||||||
|       expect(moduleDoc.docType).toEqual('module'); |  | ||||||
|       expect(getNames(moduleDoc.exports)).toEqual([ |  | ||||||
|         'OKToExport', |  | ||||||
|         '_thisIsPrivate', |  | ||||||
|         'thisIsOK' |  | ||||||
|       ]); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('interfaces', function() { |  | ||||||
| 
 |  | ||||||
|     it('should mark optional properties', function() { |  | ||||||
|       processor.sourceFiles = [ 'interfaces.ts']; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
| 
 |  | ||||||
|       var moduleDoc = docs[0]; |  | ||||||
|       var exportedInterface = moduleDoc.exports[0]; |  | ||||||
|       var member = exportedInterface.members[0]; |  | ||||||
|       expect(member.name).toEqual('optionalProperty'); |  | ||||||
|       expect(member.optional).toEqual(true); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     it('should handle "call" type interfaces', function() { |  | ||||||
|       processor.sourceFiles = [ 'interfaces.ts']; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
| 
 |  | ||||||
|       var moduleDoc = docs[0]; |  | ||||||
|       var exportedInterface = moduleDoc.exports[0]; |  | ||||||
| 
 |  | ||||||
|       expect(exportedInterface.callMember).toBeDefined(); |  | ||||||
|       expect(exportedInterface.callMember.parameters).toEqual(['param: T']); |  | ||||||
|       expect(exportedInterface.callMember.returnType).toEqual('U'); |  | ||||||
|       expect(exportedInterface.callMember.typeParameters).toEqual(['T', 'U extends Findable<T>']); |  | ||||||
|       expect(exportedInterface.newMember).toBeDefined(); |  | ||||||
|       expect(exportedInterface.newMember.parameters).toEqual(['param: number']); |  | ||||||
|       expect(exportedInterface.newMember.returnType).toEqual('MyInterface'); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('ordering of members', function() { |  | ||||||
|     it('should order class members in order of appearance (by default)', function() { |  | ||||||
|       processor.sourceFiles = ['orderingOfMembers.ts']; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
|       var classDoc = _.find(docs, { docType: 'class' }); |  | ||||||
|       expect(classDoc.docType).toEqual('class'); |  | ||||||
|       expect(getNames(classDoc.members)).toEqual([ |  | ||||||
|         'firstItem', |  | ||||||
|         'otherMethod', |  | ||||||
|         'doStuff', |  | ||||||
|       ]); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|     it('should not order class members if not sortClassMembers is false', function() { |  | ||||||
|       processor.sourceFiles = ['orderingOfMembers.ts']; |  | ||||||
|       processor.sortClassMembers = false; |  | ||||||
|       var docs = []; |  | ||||||
|       processor.$process(docs); |  | ||||||
|       var classDoc = _.find(docs, { docType: 'class' }); |  | ||||||
|       expect(classDoc.docType).toEqual('class'); |  | ||||||
|       expect(getNames(classDoc.members)).toEqual([ |  | ||||||
|         'firstItem', |  | ||||||
|         'otherMethod', |  | ||||||
|         'doStuff' |  | ||||||
|       ]); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| 
 |  | ||||||
| function getNames(collection) { |  | ||||||
|   return collection.map(function(item) { return item.name; }); |  | ||||||
| } |  | ||||||
| @ -1,31 +0,0 @@ | |||||||
| var _ = require('lodash'); |  | ||||||
| 
 |  | ||||||
| module.exports = function convertPrivateClassesToInterfaces() { |  | ||||||
|   return function(exportDocs, addInjectableReference) { |  | ||||||
|     _.forEach(exportDocs, function(exportDoc) { |  | ||||||
| 
 |  | ||||||
|       // Search for classes with a constructor marked as `@internal`
 |  | ||||||
|       if (exportDoc.docType === 'class' && exportDoc.constructorDoc && exportDoc.constructorDoc.internal) { |  | ||||||
| 
 |  | ||||||
|         // Convert this class to an interface with no constructor
 |  | ||||||
|         exportDoc.docType = 'interface'; |  | ||||||
|         exportDoc.constructorDoc = null; |  | ||||||
| 
 |  | ||||||
|         if (exportDoc.heritage) { |  | ||||||
|           // convert the heritage since interfaces use `extends` not `implements`
 |  | ||||||
|           exportDoc.heritage = exportDoc.heritage.replace('implements', 'extends'); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (addInjectableReference) { |  | ||||||
|           // Add the `declare var SomeClass extends InjectableReference` construct
 |  | ||||||
|           exportDocs.push({ |  | ||||||
|             docType: 'var', |  | ||||||
|             name: exportDoc.name, |  | ||||||
|             id: exportDoc.id, |  | ||||||
|             returnType: 'InjectableReference' |  | ||||||
|           }); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|     }); |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| @ -1,76 +0,0 @@ | |||||||
| var mockPackage = require('../mocks/mockPackage'); |  | ||||||
| var Dgeni = require('dgeni'); |  | ||||||
| var _ = require('lodash'); |  | ||||||
| 
 |  | ||||||
| describe('readTypeScriptModules', function() { |  | ||||||
|   var dgeni, injector, convertPrivateClassesToInterfaces; |  | ||||||
| 
 |  | ||||||
|   beforeEach(function() { |  | ||||||
|     dgeni = new Dgeni([mockPackage()]); |  | ||||||
|     injector = dgeni.configureInjector(); |  | ||||||
|     convertPrivateClassesToInterfaces = injector.get('convertPrivateClassesToInterfaces'); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it('should convert private class docs to interface docs', function() { |  | ||||||
|     var docs = [ |  | ||||||
|       { |  | ||||||
|         docType: 'class', |  | ||||||
|         name: 'privateClass', |  | ||||||
|         id: 'privateClass', |  | ||||||
|         constructorDoc: { internal: true } |  | ||||||
|       } |  | ||||||
|     ]; |  | ||||||
|     convertPrivateClassesToInterfaces(docs, false); |  | ||||||
|     expect(docs[0].docType).toEqual('interface'); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   it('should not touch non-private class docs', function() { |  | ||||||
|     var docs = [ |  | ||||||
|       { |  | ||||||
|         docType: 'class', |  | ||||||
|         name: 'privateClass', |  | ||||||
|         id: 'privateClass', |  | ||||||
|         constructorDoc: { } |  | ||||||
|       } |  | ||||||
|     ]; |  | ||||||
|     convertPrivateClassesToInterfaces(docs, false); |  | ||||||
|     expect(docs[0].docType).toEqual('class'); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   it('should convert the heritage since interfaces use `extends` not `implements`', function() { |  | ||||||
|     var docs = [ |  | ||||||
|       { |  | ||||||
|         docType: 'class', |  | ||||||
|         name: 'privateClass', |  | ||||||
|         id: 'privateClass', |  | ||||||
|         constructorDoc: { internal: true }, |  | ||||||
|         heritage: 'implements parentInterface' |  | ||||||
|       } |  | ||||||
|     ]; |  | ||||||
|     convertPrivateClassesToInterfaces(docs, false); |  | ||||||
|     expect(docs[0].heritage).toEqual('extends parentInterface'); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   it('should add new injectable reference types, if specified, to the passed in collection', function() { |  | ||||||
|     var docs = [ |  | ||||||
|       { |  | ||||||
|         docType: 'class', |  | ||||||
|         name: 'privateClass', |  | ||||||
|         id: 'privateClass', |  | ||||||
|         constructorDoc: { internal: true }, |  | ||||||
|         heritage: 'implements parentInterface' |  | ||||||
|       } |  | ||||||
|     ]; |  | ||||||
|     convertPrivateClassesToInterfaces(docs, true); |  | ||||||
|     expect(docs[1]).toEqual({ |  | ||||||
|       docType : 'var', |  | ||||||
|       name : 'privateClass', |  | ||||||
|       id : 'privateClass', |  | ||||||
|       returnType : 'InjectableReference' |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| }); |  | ||||||
| @ -1,3 +0,0 @@ | |||||||
| module.exports = function modules() { |  | ||||||
|   return {}; |  | ||||||
| }; |  | ||||||
| @ -1,80 +0,0 @@ | |||||||
| var ts = require('typescript'); |  | ||||||
| var fs = require('fs'); |  | ||||||
| var path = require('canonical-path'); |  | ||||||
| 
 |  | ||||||
| // We need to provide our own version of CompilerHost because we want to set the
 |  | ||||||
| // base directory and specify what extensions to consider when trying to load a source
 |  | ||||||
| // file
 |  | ||||||
| module.exports = function createCompilerHost(log) { |  | ||||||
| 
 |  | ||||||
|   return function createCompilerHost(options, baseDir, extensions) { |  | ||||||
| 
 |  | ||||||
|     return { |  | ||||||
|       getSourceFile: function(fileName, languageVersion, onError) { |  | ||||||
|         var text, resolvedPath, resolvedPathWithExt; |  | ||||||
| 
 |  | ||||||
|         // Strip off the extension and resolve relative to the baseDir
 |  | ||||||
|         baseFilePath = fileName.replace(/\.[^.]+$/, ''); |  | ||||||
|         resolvedPath = path.resolve(baseDir, baseFilePath); |  | ||||||
| 
 |  | ||||||
|         // Iterate through each possible extension and return the first source file that is actually found
 |  | ||||||
|         for(var i=0; i<extensions.length; i++) { |  | ||||||
| 
 |  | ||||||
|           // Try reading the content from files using each of the given extensions
 |  | ||||||
|           try { |  | ||||||
|             resolvedPathWithExt = resolvedPath + extensions[i]; |  | ||||||
|             log.silly('getSourceFile:', resolvedPathWithExt); |  | ||||||
|             text = fs.readFileSync(resolvedPathWithExt, { encoding: options.charset }); |  | ||||||
|             log.debug('found source file:', fileName, resolvedPathWithExt); |  | ||||||
|             return ts.createSourceFile(baseFilePath + extensions[i], text, languageVersion); |  | ||||||
|           } |  | ||||||
|           catch(e) { |  | ||||||
|             // Try again if the file simply did not exist, otherwise report the error as a warning
 |  | ||||||
|             if(e.code !== 'ENOENT') { |  | ||||||
|               if (onError) onError(e.message); |  | ||||||
|               log.warn('Error reading ' + resolvedPathWithExt + ' : ' + e.message); |  | ||||||
|             } |  | ||||||
|           } |  | ||||||
|         } |  | ||||||
|       }, |  | ||||||
|       getDefaultLibFileName: function(options) { |  | ||||||
|         return path.resolve(path.dirname(ts.sys.getExecutingFilePath()), ts.getDefaultLibFileName(options)); |  | ||||||
|       }, |  | ||||||
|       writeFile: function(fileName, data, writeByteOrderMark, onError) { |  | ||||||
|         // no-op
 |  | ||||||
|       }, |  | ||||||
|       getCurrentDirectory: function() { |  | ||||||
|         return baseDir; |  | ||||||
|       }, |  | ||||||
|       useCaseSensitiveFileNames: function() { |  | ||||||
|         return ts.sys.useCaseSensitiveFileNames; |  | ||||||
|       }, |  | ||||||
|       getCanonicalFileName: function(fileName) { |  | ||||||
|         // if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
 |  | ||||||
|         // otherwise use toLowerCase as a canonical form.
 |  | ||||||
|         return ts.sys.useCaseSensitiveFileNames ? fileName : fileName.toLowerCase(); |  | ||||||
|       }, |  | ||||||
|       getNewLine: function() { |  | ||||||
|         return ts.sys.newLine; |  | ||||||
|       }, |  | ||||||
|       fileExists(fileName) { |  | ||||||
|         var text, resolvedPath, resolvedPathWithExt; |  | ||||||
| 
 |  | ||||||
|         // Strip off the extension and resolve relative to the baseDir
 |  | ||||||
|         baseFilePath = fileName.replace(/\.[^.]+$/, ''); |  | ||||||
|         resolvedPath = path.resolve(baseDir, baseFilePath); |  | ||||||
| 
 |  | ||||||
|         // Iterate through each possible extension and return the first source file that is actually found
 |  | ||||||
|         for(var i=0; i<extensions.length; i++) { |  | ||||||
|           // Try reading the content from files using each of the given extensions
 |  | ||||||
|           resolvedPathWithExt = resolvedPath + extensions[i]; |  | ||||||
|           if (fs.existsSync(resolvedPathWithExt)) return true; |  | ||||||
|         } |  | ||||||
|         return false; |  | ||||||
|       }, |  | ||||||
|       readFile(fileName) { |  | ||||||
|         console.log('readFile - NOT IMPLEMENTED', fileName); |  | ||||||
|       } |  | ||||||
|     }; |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| @ -1,80 +0,0 @@ | |||||||
| var mockPackage = require('../../mocks/mockPackage'); |  | ||||||
| var Dgeni = require('dgeni'); |  | ||||||
| var path = require('canonical-path'); |  | ||||||
| var ts = require('typescript'); |  | ||||||
| 
 |  | ||||||
| describe('createCompilerHost', function() { |  | ||||||
|   var dgeni, injector, options, host, baseDir, extensions; |  | ||||||
| 
 |  | ||||||
|   beforeEach(function() { |  | ||||||
|     dgeni = new Dgeni([mockPackage()]); |  | ||||||
|     injector = dgeni.configureInjector(); |  | ||||||
|     var createCompilerHost = injector.get('createCompilerHost'); |  | ||||||
| 
 |  | ||||||
|     options = { charset: 'utf8' }; |  | ||||||
|     baseDir = path.resolve(__dirname, '../../mocks/tsParser'); |  | ||||||
|     extensions = ['.ts', '.js']; |  | ||||||
| 
 |  | ||||||
|     host = createCompilerHost(options, baseDir, extensions); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   describe('getSourceFile', function() { |  | ||||||
|     it('should return a SourceFile object for a given path, with fileName relative to baseDir', function() { |  | ||||||
|       var sourceFile = host.getSourceFile('testSrc.ts'); |  | ||||||
|       expect(sourceFile.fileName).toEqual('testSrc.ts'); |  | ||||||
|       expect(sourceFile.pos).toEqual(0); |  | ||||||
|       expect(sourceFile.text).toEqual(jasmine.any(String)); |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     it('should try each of the configured extensions and update the filename to the correct extension', function() { |  | ||||||
|       var sourceFile = host.getSourceFile('testSrc.js'); |  | ||||||
|       expect(sourceFile.fileName).toEqual('testSrc.ts'); |  | ||||||
| 
 |  | ||||||
|       sourceFile = host.getSourceFile('../mockPackage.ts'); |  | ||||||
|       expect(sourceFile.fileName).toEqual('../mockPackage.js'); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('getDefaultLibFileName', function() { |  | ||||||
|     it('should return a path to the default library', function() { |  | ||||||
|       expect(host.getDefaultLibFileName(options)).toContain('typescript/lib/lib.d.ts'); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('writeFile', function() { |  | ||||||
|     it('should do nothing', function() { |  | ||||||
|       host.writeFile(); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('getCurrentDirectory', function() { |  | ||||||
|     it('should return the baseDir', function() { |  | ||||||
|       expect(host.getCurrentDirectory()).toEqual(baseDir); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('useCaseSensitiveFileNames', function() { |  | ||||||
|     it('should return true if the OS is case sensitive', function() { |  | ||||||
|       expect(host.useCaseSensitiveFileNames()).toBe(ts.sys.useCaseSensitiveFileNames); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('getCanonicalFileName', function() { |  | ||||||
|     it('should lower case the filename', function() { |  | ||||||
|       var expectedFilePath = host.useCaseSensitiveFileNames() ? 'SomeFile.ts' : 'somefile.ts'; |  | ||||||
|       expect(host.getCanonicalFileName('SomeFile.ts')).toEqual(expectedFilePath); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   describe('getNewLine', function() { |  | ||||||
|     it('should return the newline character for the OS', function() { |  | ||||||
|       expect(host.getNewLine()).toEqual(require('os').EOL); |  | ||||||
|     }); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
| @ -1,49 +0,0 @@ | |||||||
| var ts = require('typescript'); |  | ||||||
| var LEADING_STAR = /^[^\S\r\n]*\*[^\S\n\r]?/gm; |  | ||||||
| 
 |  | ||||||
| module.exports = function getContent() { |  | ||||||
|   return function(symbol) { |  | ||||||
| 
 |  | ||||||
|     var content = ""; |  | ||||||
| 
 |  | ||||||
|     if (!symbol.declarations) return content; |  | ||||||
| 
 |  | ||||||
|     symbol.declarations.forEach(function(declaration) { |  | ||||||
| 
 |  | ||||||
|       // If this is left side of dotted module declaration, there is no doc comment associated with this declaration
 |  | ||||||
|       if (declaration.kind === ts.SyntaxKind.ModuleDeclaration && declaration.body.kind === ts.SyntaxKind.ModuleDeclaration) { |  | ||||||
|           return content; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       // If this is dotted module name, get the doc comments from the parent
 |  | ||||||
|       while (declaration.kind === ts.SyntaxKind.ModuleDeclaration && declaration.parent.kind === ts.SyntaxKind.ModuleDeclaration) { |  | ||||||
|           declaration = declaration.parent; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       // If this is a variable declaration then we get the doc comments from the grand parent
 |  | ||||||
|       if (declaration.kind === ts.SyntaxKind.VariableDeclaration) { |  | ||||||
|         declaration = declaration.parent.parent; |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       // Get the source file of this declaration
 |  | ||||||
|       var sourceFile = ts.getSourceFileOfNode(declaration); |  | ||||||
|       var commentRanges = ts.getJsDocComments(declaration, sourceFile); |  | ||||||
| 
 |  | ||||||
|       if (commentRanges) { |  | ||||||
|         commentRanges.forEach(function(commentRange) { |  | ||||||
|           content += sourceFile.text |  | ||||||
|               .substring(commentRange.pos+ '/**'.length, commentRange.end - '*/'.length) |  | ||||||
|               .replace(LEADING_STAR, '') |  | ||||||
|               .trim(); |  | ||||||
|           if (commentRange.hasTrailingNewLine) { |  | ||||||
|             content += '\n'; |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       content += '\n'; |  | ||||||
|     }); |  | ||||||
| 
 |  | ||||||
|     return content; |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| @ -1,54 +0,0 @@ | |||||||
| var ts = require('typescript'); |  | ||||||
| 
 |  | ||||||
| module.exports = function getExportDocType(log) { |  | ||||||
| 
 |  | ||||||
|   return function(symbol) { |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.Function) { |  | ||||||
|       return 'function'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.Class) { |  | ||||||
|       return 'class'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.Interface) { |  | ||||||
|       return 'interface'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.ConstEnum) { |  | ||||||
|       return 'enum'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.RegularEnum) { |  | ||||||
|       return 'enum'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.Property) { |  | ||||||
|       return 'module-property'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.TypeAlias) { |  | ||||||
|       return 'type-alias'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.FunctionScopedVariable) { |  | ||||||
|       return 'var'; |  | ||||||
|     } |  | ||||||
|     if(symbol.flags & ts.SymbolFlags.BlockScopedVariable) { |  | ||||||
|       return getBlockScopedVariableDocType(symbol); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     log.warn('getExportDocType(): Unknown symbol type', { |  | ||||||
|       symbolName: symbol.name, |  | ||||||
|       symbolType: symbol.flags, |  | ||||||
|       symbolTarget: symbol.target, |  | ||||||
|       file: ts.getSourceFileOfNode(symbol.declarations[0]).fileName |  | ||||||
|     }); |  | ||||||
|     return 'unknown'; |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
|   function getBlockScopedVariableDocType(symbol) { |  | ||||||
| 
 |  | ||||||
|     var node = symbol.valueDeclaration; |  | ||||||
|     while(node) { |  | ||||||
|       if ( node.flags & 0x2000 /* const */) { |  | ||||||
|         return 'const'; |  | ||||||
|       } |  | ||||||
|       node = node.parent; |  | ||||||
|     } |  | ||||||
|     return 'let'; |  | ||||||
|   } |  | ||||||
| }; |  | ||||||
| @ -1,20 +0,0 @@ | |||||||
| var path = require('canonical-path'); |  | ||||||
| var ts = require('typescript'); |  | ||||||
| 
 |  | ||||||
| module.exports = function getFileInfo(log) { |  | ||||||
| 
 |  | ||||||
|   return function (symbol, basePath) { |  | ||||||
|     var fileName = ts.getSourceFileOfNode(symbol.declarations[0]).fileName; |  | ||||||
| 
 |  | ||||||
|     var file = path.resolve(basePath, fileName); |  | ||||||
|     var fileInfo = { |  | ||||||
|       filePath: file, |  | ||||||
|       baseName: path.basename(file, path.extname(file)), |  | ||||||
|       extension: path.extname(file).replace(/^\./, ''), |  | ||||||
|       basePath: basePath, |  | ||||||
|       relativePath: fileName, |  | ||||||
|       projectRelativePath: fileName |  | ||||||
|     }; |  | ||||||
|     return fileInfo; |  | ||||||
|   }; |  | ||||||
| }; |  | ||||||
| @ -1,74 +0,0 @@ | |||||||
| var ts = require('typescript'); |  | ||||||
| var path = require('canonical-path'); |  | ||||||
| 
 |  | ||||||
| module.exports = function tsParser(createCompilerHost, log) { |  | ||||||
| 
 |  | ||||||
|   return { |  | ||||||
| 
 |  | ||||||
|     // These are the extension that we should consider when trying to load a module
 |  | ||||||
|     // During migration from Traceur, there is a mix of `.ts`, `.es6` and `.js` (atScript)
 |  | ||||||
|     // files in the project and the TypeScript compiler only looks for `.ts` files when trying
 |  | ||||||
|     // to load imports.
 |  | ||||||
|     extensions: ['.ts', '.js'], |  | ||||||
| 
 |  | ||||||
|     // The options for the TS compiler
 |  | ||||||
|     options: { |  | ||||||
|       allowNonTsExtensions: true, |  | ||||||
|       charset: 'utf8' |  | ||||||
|     }, |  | ||||||
| 
 |  | ||||||
|     parse: function(fileNames, baseDir) { |  | ||||||
| 
 |  | ||||||
|       // "Compile" a program from the given module filenames, to get hold of a
 |  | ||||||
|       // typeChecker that can be used to interrogate the modules, exports and so on.
 |  | ||||||
|       var host = createCompilerHost(this.options, baseDir, this.extensions); |  | ||||||
|       var program = ts.createProgram(fileNames, this.options, host); |  | ||||||
|       var typeChecker = program.getTypeChecker(); |  | ||||||
| 
 |  | ||||||
|       // Create an array of module symbols for each file we were given
 |  | ||||||
|       var moduleSymbols = []; |  | ||||||
|       fileNames.forEach(function(fileName) { |  | ||||||
|         var sourceFile = program.getSourceFile(fileName); |  | ||||||
| 
 |  | ||||||
|         if (!sourceFile) { |  | ||||||
|           throw new Error('Invalid source file: ' + fileName); |  | ||||||
|         } else if (!sourceFile.symbol) { |  | ||||||
|           // Some files contain only a comment and no actual module code
 |  | ||||||
|           log.warn('No module code found in ' + fileName); |  | ||||||
|         } else { |  | ||||||
|           moduleSymbols.push(sourceFile.symbol); |  | ||||||
|         } |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|       moduleSymbols.forEach(function(tsModule) { |  | ||||||
| 
 |  | ||||||
|         // The type checker has a nice helper function that returns an array of Symbols
 |  | ||||||
|         // representing the exports for a given module
 |  | ||||||
|         tsModule.exportArray = typeChecker.getExportsOfModule(tsModule); |  | ||||||
| 
 |  | ||||||
|         // Although 'star' imports (e.g. `export * from 'some/module';) get resolved automatically
 |  | ||||||
|         // by the compiler/binder, it seems that explicit imports (e.g. `export {SomeClass} from 'some/module'`)
 |  | ||||||
|         // do not so we have to do a little work.
 |  | ||||||
|         tsModule.exportArray.forEach(function(moduleExport) { |  | ||||||
|           if (moduleExport.flags & ts.SymbolFlags.Alias) { |  | ||||||
|             // To maintain the alias information (particularly the alias name)
 |  | ||||||
|             // we just attach the original "resolved" symbol to the alias symbol
 |  | ||||||
|             moduleExport.resolvedSymbol = typeChecker.getAliasedSymbol(moduleExport); |  | ||||||
|           } |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       moduleSymbols.typeChecker = typeChecker; |  | ||||||
| 
 |  | ||||||
|       return { |  | ||||||
|         moduleSymbols: moduleSymbols, |  | ||||||
|         typeChecker: typeChecker, |  | ||||||
|         program: program, |  | ||||||
|         host: host |  | ||||||
|       }; |  | ||||||
|     } |  | ||||||
|   }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
| @ -1,21 +0,0 @@ | |||||||
| var mockPackage = require('../../mocks/mockPackage'); |  | ||||||
| var Dgeni = require('dgeni'); |  | ||||||
| var path = require('canonical-path'); |  | ||||||
| 
 |  | ||||||
| describe('tsParser', function() { |  | ||||||
|   var dgeni, injector, parser; |  | ||||||
| 
 |  | ||||||
|   beforeEach(function() { |  | ||||||
|     dgeni = new Dgeni([mockPackage()]); |  | ||||||
|     injector = dgeni.configureInjector(); |  | ||||||
|     parser = injector.get('tsParser'); |  | ||||||
|   }); |  | ||||||
| 
 |  | ||||||
|   it("should parse a TS file", function() { |  | ||||||
|     var parseInfo = parser.parse(['testSrc.ts'], path.resolve(__dirname, '../../mocks/tsParser')); |  | ||||||
|     var tsModules = parseInfo.moduleSymbols; |  | ||||||
|     expect(tsModules.length).toEqual(1); |  | ||||||
|     expect(tsModules[0].exportArray.length).toEqual(3); |  | ||||||
|     expect(tsModules[0].exportArray.map(function(i) { return i.name; })).toEqual(['MyClass', 'myFn', 'x']); |  | ||||||
|   }); |  | ||||||
| }); |  | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user