UNPKG

nodent

Version:

NoDent - Asynchronous Javascript language extensions

123 lines (108 loc) 3.53 kB
/* Test parser/output routines, not async transformations */ var nodent = require('../nodent.js')() ; var fs = require('fs'); var n = 0 ; /* For each example, read it, parse it, output it, parse it again and check the trees & code strings are the same */ //List all files in a directory in Node.js recursively in a synchronous fashion function walkSync(dir, filelist) { filelist = filelist || []; if( dir[dir.length-1] != '/') dir=dir.concat('/') var fs = fs || require('fs'), files = fs.readdirSync(dir); filelist = filelist || []; files.forEach(function(file) { var stat = fs.lstatSync(dir + file) ; if (!stat.isSymbolicLink()) { if (stat.isDirectory()) filelist = walkSync(dir + file + '/', filelist); else filelist.push(dir+file); } }); return filelist; }; var diff = require('./onp/diff') ; function testFiles(paths,recurse) { var pass = [] ; paths.forEach(function(fn){ if (fs.statSync(fn).isDirectory()) { walkSync(fn,pass) ; } else { pass.push(fn) ; } }) ; pass = pass.filter(function(fn){ return fn.match(/\.js$/)}) ; console.log("Syntax check - "+pass.length+" test files installed....") ; pass.forEach(function(fn,idx){ if (idx && idx%1000==0) { console.error('Tested '+idx+'. '+(idx-n)+' fails so far...') ; } var code = fs.readFileSync(fn).toString() ; try { var r = {name:fn, toString:function(){ return this.name+": "+(this.error||"") +(this.diff?"\n"+this.diff.summary():"") +(this.tree?"\n"+this.tree.summary():"") ; }} ; var opts = {parser:{sourceType:'script',allowImportExportEverywhere:true,onComment:null}} ; try { var initialAST = nodent.parse(code,"",null,opts) ; var ci = nodent.prettyPrint(initialAST,opts) ; } catch(ex) { opts.parser.sourceType = 'module' ; ci = nodent.prettyPrint(nodent.parse(code,"",null,opts),opts) ; } var co = nodent.prettyPrint(nodent.parse(ci.code,"",null,opts)) ; r.diff = diff(ci.code,co.code) ; eqTree(ci.ast,co.ast) ; if (!r.diff.diff) { n += 1 ; return {name:fn} ; } else { console.log(r.error = r.toString()) ; return r ; } } catch (ex) { if (!initialAST) { n += 1 ; r.error = "Not valid javascript (ignored "+opts.parser.sourceType+")" ; } else { r.error = ex.message ; if (ci && co && ci.ast && co.ast) { var inTree = JSON.stringify(ci.ast,noLocations,2) ; var outTree = JSON.stringify(co.ast,noLocations,2) ; r.tree = diff(inTree,outTree) ; } } console.log(r.toString()) ; return r ; } }) ; if (n===pass.length) console.log("Syntax check - pass "+n+" of "+pass.length) ; else if (pass.length<1000) { console.log("Syntax check - FAIL "+(pass.length-n)+" of "+pass.length) ; } } function noLocations(k,v) { return locations(k)?v:undefined ; } function locations(k) { return ['end','start','loc'].indexOf(k)<0 ; } debugger ; function eqTree(a,b,p) { if (!p) p = "" ; var ka = Object.keys(a).filter(locations).sort() ; var kb = Object.keys(b).filter(locations).sort() ; if (ka.length > kb.length) throw new Error("length("+ka.length+","+kb.length+") "+p) ; for (var i=0;i<ka.length;i++) if (typeof a[ka[i]] != typeof b[ka[i]] || (!(a[ka[i]] instanceof Object) && a[ka[i]] !== b[ka[i]])) throw new Error("key("+ka[i]+","+ka[i]+") "+p) ; for (var i=0;i<ka.length;i++) if (typeof a[ka[i]] === 'object' && a[ka[i]]) eqTree(a[ka[i]],b[ka[i]],p+" > "+ka[i]+":"+a[ka[i]].type) ; return true ; } module.exports = {testFiles:testFiles} ;