find-elm-dependencies
Version:
Find elm dependencies
98 lines (82 loc) • 2.77 kB
JavaScript
const stream = require('stream');
const fs = require('fs');
/* Read imports from a given file and return them
*/
function readImports(file){
return new Promise(function(resolve, reject){
// read 60 chars at a time. roughly optimal: memory vs performance
var stream = fs.createReadStream(file, {encoding: 'utf8', highWaterMark: 8 * 60});
var buffer = "";
var parser = new Parser();
stream.on('error', function () {
// failed to process the file, so return null
resolve(null);
});
stream.on('data', function(chunk){
buffer += chunk;
// when the chunk has a newline, process each line
if (chunk.indexOf('\n') > -1){
var lines = buffer.split('\n');
lines.slice(0, lines.length - 1).forEach(parser.parseLine.bind(parser));
buffer = lines[lines.length - 1];
// end the stream early if we're past the imports
// to save on memory
if (parser.isPastImports()){
stream.destroy();
}
}
});
stream.on('close', function (){
resolve(parser.getImports());
});
});
}
function Parser(){
var moduleRead = false;
var readingImports = false;
var parsingDone = false;
var isInComment = false;
var imports = [];
this.parseLine = function(line){
if (parsingDone) return;
if (!moduleRead &&
(line.startsWith('module ')
|| line.startsWith('port module')
|| line.startsWith('effect module')
)
) {
moduleRead = true;
} else if (moduleRead && line.indexOf('import ') === 0){
readingImports = true;
}
if (isInComment) {
if (line.endsWith('-}')){
isInComment = false;
}
return;
}
if (readingImports){
if (line.indexOf('import ') === 0){
imports.push(line);
} else if (line.indexOf(' ') === 0 || line.trim().length === 0 || line.startsWith('--') ) {
// ignore lines starting with whitespace while parsing imports
// and start and end of comments
} else if (line.startsWith('{-')) {
isInComment = true;
} else {
// console.log('detected end of imports', line);
parsingDone = true;
}
}
};
this.getImports = function(){
return imports;
}
this.isPastImports = function(){
return parsingDone;
}
return this;
}
module.exports = {
readImports: readImports
};