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 {
// 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: {
allowNonTsExtensions: true
allowNonTsExtensions: true,
charset: 'utf8'
},
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
// 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 typeChecker = program.getTypeChecker();

View File

@ -1,32 +1,62 @@
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
var extensions = ['.ts', '.js', '.es6']
// 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.
// 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) {
var host = ts.createCompilerHost(options);
return function createCompilerHost(options, baseDir, extensions) {
// Override the `getSourceFile` implementation to also look for js and es6 files
var getSourceFile = host.getSourceFile;
host.getSourceFile = function(filename, languageVersion, onError) {
// Iterate through each possible extension and return the first source file that is actually found
for(var i=0; i<extensions.length; i++) {
var extension = extensions[i];
var altFileName = filename.replace(/\.ts$/, extension);
log.silly('getSourceFile:', altFileName);
var sourceFile = getSourceFile.call(host, altFileName, languageVersion, onError);
if(sourceFile) {
log.debug('found source file:', altFileName);
return sourceFile;
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;
}
};
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);
});
});
});