chore(doc-gen): get CompilerHost to return the SourceFiles with the correct fileName

Now that we are not changing the working directory, we needed to update how
getSourceFiles works to ensure that it worked relative to the baseDir.
This commit is contained in:
Peter Bacon Darwin 2015-05-19 12:53:37 +01:00
parent ba80bd43ad
commit 118f0520a2
3 changed files with 140 additions and 27 deletions

View File

@ -5,18 +5,23 @@ module.exports = function tsParser(createCompilerHost, log) {
return { 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', '.es6'],
// The options for the TS compiler
options: { options: {
allowNonTsExtensions: true allowNonTsExtensions: true,
charset: 'utf8'
}, },
parse: function(fileNames, baseDir) { parse: function(fileNames, baseDir) {
fileNames = fileNames.map(function(fileName) {
return path.resolve(baseDir, fileName);
});
// "Compile" a program from the given module filenames, to get hold of a // "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. // typeChecker that can be used to interrogate the modules, exports and so on.
var host = createCompilerHost(this.options); var host = createCompilerHost(this.options, baseDir, this.extensions);
var program = ts.createProgram(fileNames, this.options, host); var program = ts.createProgram(fileNames, this.options, host);
var typeChecker = program.getTypeChecker(); var typeChecker = program.getTypeChecker();

View File

@ -1,32 +1,62 @@
var ts = require('typescript'); var ts = require('typescript');
var fs = require('fs');
var path = require('canonical-path');
// These are the extension that we should consider when trying to load a module // We need to provide our own version of CompilerHost because we want to set the
var extensions = ['.ts', '.js', '.es6'] // base directory and specify what extensions to consider when trying to load a source
// file
// We need to provide our own version of CompilerHost because, at the moment, 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.
module.exports = function createCompilerHost(log) { module.exports = function createCompilerHost(log) {
return function createCompilerHost(options) {
var host = ts.createCompilerHost(options); return function createCompilerHost(options, baseDir, extensions) {
// Override the `getSourceFile` implementation to also look for js and es6 files return {
var getSourceFile = host.getSourceFile; getSourceFile: function(fileName, languageVersion, onError) {
host.getSourceFile = function(filename, languageVersion, onError) { var text, resolvedPath, resolvedPathWithExt;
// Iterate through each possible extension and return the first source file that is actually found
for(var i=0; i<extensions.length; i++) { // Strip off the extension and resolve relative to the baseDir
var extension = extensions[i]; baseFilePath = fileName.replace(/\.[^.]+$/, '');
var altFileName = filename.replace(/\.ts$/, extension); resolvedPath = path.resolve(baseDir, baseFilePath);
log.silly('getSourceFile:', altFileName);
var sourceFile = getSourceFile.call(host, altFileName, languageVersion, onError); // Iterate through each possible extension and return the first source file that is actually found
if(sourceFile) { for(var i=0; i<extensions.length; i++) {
log.debug('found source file:', altFileName);
return sourceFile; // 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;
} }
}; };
return host;
}; };
}; };

View File

@ -0,0 +1,78 @@
var mockPackage = require('../../mocks/mockPackage');
var Dgeni = require('dgeni');
var path = require('canonical-path');
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/');
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 false', function() {
expect(host.useCaseSensitiveFileNames()).toBe(false);
});
});
describe('getCanonicalFileName', function() {
it('should lower case the filename', function() {
expect(host.getCanonicalFileName('SomeFile.ts')).toEqual('somefile.ts');
});
});
describe('getNewLine', function() {
it('should return the newline character for the OS', function() {
expect(host.getNewLine()).toEqual(require('os').EOL);
});
});
});