75 lines
2.6 KiB
JavaScript
75 lines
2.6 KiB
JavaScript
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
|
|
};
|
|
}
|
|
};
|
|
|
|
|
|
};
|