69 lines
2.3 KiB
JavaScript
69 lines
2.3 KiB
JavaScript
|
var ts = require('typescript');
|
||
|
|
||
|
module.exports = function tsParser(createCompilerHost, log) {
|
||
|
|
||
|
return {
|
||
|
|
||
|
options: {
|
||
|
allowNonTsExtensions: true
|
||
|
},
|
||
|
|
||
|
parse: function(fileNames, baseDir) {
|
||
|
// This is the easiest way I could find to ensure that we loaded
|
||
|
// modules with paths relative to the baseDir
|
||
|
process.chdir(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);
|
||
|
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 & 8388608 /* 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
|
||
|
};
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
};
|