mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +08:00
docs wip
This commit is contained in:
10
gulpfile.js
10
gulpfile.js
@ -22,6 +22,7 @@ var tsc = require('gulp-typescript');
|
|||||||
var lazypipe = require('lazypipe');
|
var lazypipe = require('lazypipe');
|
||||||
var cache = require('gulp-cached');
|
var cache = require('gulp-cached');
|
||||||
var connect = require('gulp-connect');
|
var connect = require('gulp-connect');
|
||||||
|
var Dgeni = require('dgeni');
|
||||||
|
|
||||||
function getBabelOptions(moduleName) {
|
function getBabelOptions(moduleName) {
|
||||||
return {
|
return {
|
||||||
@ -289,3 +290,12 @@ gulp.task('karma', function() {
|
|||||||
gulp.task('karma-watch', function() {
|
gulp.task('karma-watch', function() {
|
||||||
return karma.start({ configFile: __dirname + '/scripts/test/karma-watch.conf.js' })
|
return karma.start({ configFile: __dirname + '/scripts/test/karma-watch.conf.js' })
|
||||||
});
|
});
|
||||||
|
|
||||||
|
gulp.task('docs', function() {
|
||||||
|
try {
|
||||||
|
var dgeni = new Dgeni([require('./scripts/docs/dgeni-config')]);
|
||||||
|
return dgeni.generate();
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err.stack);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
"canonical-path": "0.0.2",
|
"canonical-path": "0.0.2",
|
||||||
"connect": "^3.3.4",
|
"connect": "^3.3.4",
|
||||||
"del": "~1.1.1",
|
"del": "~1.1.1",
|
||||||
|
"dgeni": "^0.4.1",
|
||||||
|
"dgeni-packages": "^0.10.18",
|
||||||
"gulp": "~3.8.10",
|
"gulp": "~3.8.10",
|
||||||
"gulp-autoprefixer": "^2.3.0",
|
"gulp-autoprefixer": "^2.3.0",
|
||||||
"gulp-babel": "^5.1.0",
|
"gulp-babel": "^5.1.0",
|
||||||
|
32
scripts/docs/dgeni-config.js
Normal file
32
scripts/docs/dgeni-config.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
var Package = require('dgeni').Package;
|
||||||
|
var jsdocPackage = require('dgeni-packages/jsdoc');
|
||||||
|
var nunjucksPackage = require('dgeni-packages/nunjucks');
|
||||||
|
var typescriptPackage = require('./typescript-package');
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
|
// Define the dgeni package for generating the docs
|
||||||
|
module.exports = new Package('ionic-v2-docs', [jsdocPackage, nunjucksPackage, typescriptPackage/*, linksPackage, gitPackage*/])
|
||||||
|
|
||||||
|
.config(function(log) {
|
||||||
|
log.level = 'debug' //'warn';
|
||||||
|
})
|
||||||
|
|
||||||
|
.config(function(readFilesProcessor, inlineTagProcessor, readTypeScriptModules, createTypeDefinitionFile) {
|
||||||
|
|
||||||
|
// Don't run unwanted processors
|
||||||
|
readFilesProcessor.$enabled = false; // We are not using the normal file reading processor
|
||||||
|
inlineTagProcessor.$enabled = false; // We are not actually processing the inline link tags
|
||||||
|
|
||||||
|
// jsdocFileReader.defaultPattern = /\.(j|t)s$/;
|
||||||
|
// readFilesProcessor.fileReaders = [jsdocFileReader];
|
||||||
|
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
|
||||||
|
readTypeScriptModules.basePath = path.resolve(path.resolve(__dirname, '../..'));
|
||||||
|
// readFilesProcessor.sourceFiles = [
|
||||||
|
// { include: 'ionic/**/*.ts', basePath: 'ionic' }
|
||||||
|
// ]
|
||||||
|
readTypeScriptModules.sourceFiles = [
|
||||||
|
'ionic/ionic.ts'
|
||||||
|
];
|
||||||
|
|
||||||
|
writeFilesProcessor.outputFolder = 'dist/docs'
|
||||||
|
});
|
70
scripts/docs/typescript-package/index.js
Normal file
70
scripts/docs/typescript-package/index.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
require('../../tools/transpiler/index.js').init();
|
||||||
|
|
||||||
|
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('EXPORT_DOC_TYPES', function() {
|
||||||
|
return [
|
||||||
|
'class',
|
||||||
|
'interface',
|
||||||
|
'function',
|
||||||
|
'var',
|
||||||
|
'const',
|
||||||
|
'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.id]; }
|
||||||
|
});
|
||||||
|
|
||||||
|
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'
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
11
scripts/docs/typescript-package/mocks/mockPackage.js
Normal file
11
scripts/docs/typescript-package/mocks/mockPackage.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
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 {}; });
|
||||||
|
|
||||||
|
};
|
@ -0,0 +1,4 @@
|
|||||||
|
export var __esModule = true;
|
||||||
|
export class OKToExport {}
|
||||||
|
export function _thisIsPrivate() {}
|
||||||
|
export var thisIsOK = '!';
|
@ -0,0 +1,5 @@
|
|||||||
|
export interface MyInterface {
|
||||||
|
optionalProperty? : string
|
||||||
|
<T, U extends Findable<T>>(param: T) : U
|
||||||
|
new (param: number) : MyInterface
|
||||||
|
}
|
@ -0,0 +1,6 @@
|
|||||||
|
export class Test {
|
||||||
|
firstItem;
|
||||||
|
constructor() { this.doStuff(); }
|
||||||
|
otherMethod() {}
|
||||||
|
doStuff() {}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
export var x = 100;
|
34
scripts/docs/typescript-package/mocks/tsParser/testSrc.ts
Normal file
34
scripts/docs/typescript-package/mocks/tsParser/testSrc.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* @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;
|
@ -0,0 +1,342 @@
|
|||||||
|
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, 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'],
|
||||||
|
|
||||||
|
$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;
|
||||||
|
var exportDoc = createExportDoc(exportSymbol.name, resolvedExport, moduleDoc, basePath, parseInfo.typeChecker);
|
||||||
|
log.debug('>>>> EXPORT: ' + exportDoc.name + ' (' + exportDoc.docType + ') from ' + moduleDoc.id);
|
||||||
|
|
||||||
|
// Generate docs for each of the export's members
|
||||||
|
if (resolvedExport.flags & ts.SymbolFlags.HasMembers) {
|
||||||
|
|
||||||
|
exportDoc.members = [];
|
||||||
|
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 (sortClassMembers) {
|
||||||
|
exportDoc.members.sort(function(a, b) {
|
||||||
|
if (a.name > b.name) return 1;
|
||||||
|
if (a.name < b.name) return -1;
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exportDoc.docType == 'enum') {
|
||||||
|
exportDoc.members = [];
|
||||||
|
for (var etype in resolvedExport.exports) {
|
||||||
|
exportDoc.members.push(etype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add this export doc to its module doc
|
||||||
|
moduleDoc.exports.push(exportDoc);
|
||||||
|
docs.push(exportDoc);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function createModuleDoc(moduleSymbol, basePath) {
|
||||||
|
var id = moduleSymbol.name.replace(/^"|"$/g, '');
|
||||||
|
var moduleDoc = {
|
||||||
|
docType: 'module',
|
||||||
|
id: id,
|
||||||
|
aliases: [id],
|
||||||
|
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 = '';
|
||||||
|
|
||||||
|
exportSymbol.declarations.forEach(function(decl) {
|
||||||
|
var sourceFile = ts.getSourceFileOfNode(decl);
|
||||||
|
|
||||||
|
if (decl.typeParameters) {
|
||||||
|
typeParamString = '<' + getText(sourceFile, decl.typeParameters) + '>';
|
||||||
|
}
|
||||||
|
|
||||||
|
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),
|
||||||
|
name: name,
|
||||||
|
id: moduleDoc.id + '/' + name,
|
||||||
|
typeParams: typeParamString,
|
||||||
|
heritage: heritageString,
|
||||||
|
aliases: aliasNames,
|
||||||
|
moduleDoc: moduleDoc,
|
||||||
|
content: getContent(exportSymbol),
|
||||||
|
fileInfo: getFileInfo(exportSymbol, basePath),
|
||||||
|
location: getLocation(exportSymbol)
|
||||||
|
};
|
||||||
|
|
||||||
|
if(exportSymbol.flags & ts.SymbolFlags.Function) {
|
||||||
|
exportDoc.parameters = getParameters(typeChecker, exportSymbol);
|
||||||
|
}
|
||||||
|
if(exportSymbol.flags & ts.SymbolFlags.Value) {
|
||||||
|
exportDoc.returnType = getReturnType(typeChecker, exportSymbol);
|
||||||
|
}
|
||||||
|
return exportDoc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createMemberDoc(memberSymbol, classDoc, basePath, typeChecker) {
|
||||||
|
var memberDoc = {
|
||||||
|
docType: 'member',
|
||||||
|
classDoc: classDoc,
|
||||||
|
name: memberSymbol.name,
|
||||||
|
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 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 = getText(sourceFile, parameter.name);
|
||||||
|
if (parameter.questionToken || parameter.initializer) {
|
||||||
|
paramText += '?';
|
||||||
|
}
|
||||||
|
if (parameter.type) {
|
||||||
|
paramText += ':' + getType(sourceFile, parameter.type);
|
||||||
|
} else {
|
||||||
|
paramText += ': any';
|
||||||
|
}
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 Rx
|
||||||
|
if (text.match(/^\s*Rx\./)) 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;
|
||||||
|
}
|
@ -0,0 +1,115 @@
|
|||||||
|
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('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; });
|
||||||
|
}
|
3
scripts/docs/typescript-package/services/modules.js
Normal file
3
scripts/docs/typescript-package/services/modules.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
module.exports = function modules() {
|
||||||
|
return {};
|
||||||
|
};
|
@ -0,0 +1,62 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,80 @@
|
|||||||
|
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/bin/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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,49 @@
|
|||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
@ -0,0 +1,56 @@
|
|||||||
|
var ts = require('typescript');
|
||||||
|
|
||||||
|
module.exports = function getExportDocType(log) {
|
||||||
|
|
||||||
|
return function(symbol) {
|
||||||
|
if(symbol.flags & ts.SymbolFlags.FunctionScopedVariable) {
|
||||||
|
return 'var';
|
||||||
|
}
|
||||||
|
if(symbol.flags & ts.SymbolFlags.BlockScopedVariable) {
|
||||||
|
return getBlockScopedVariableDocType(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';
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */) {
|
||||||
|
// DefinitelyTyped is still TS 1.4 so const is not allowed.
|
||||||
|
// https://github.com/borisyankov/DefinitelyTyped/issues/4564
|
||||||
|
return 'var'; // change to const when targetting TS 1.5
|
||||||
|
}
|
||||||
|
node = node.parent;
|
||||||
|
}
|
||||||
|
return 'let';
|
||||||
|
}
|
||||||
|
};
|
@ -0,0 +1,20 @@
|
|||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
74
scripts/docs/typescript-package/services/tsParser/index.js
Normal file
74
scripts/docs/typescript-package/services/tsParser/index.js
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
};
|
@ -0,0 +1,21 @@
|
|||||||
|
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']);
|
||||||
|
});
|
||||||
|
});
|
Reference in New Issue
Block a user