UNPKG

scoped

Version:

command line tool exposing lexical-scope

235 lines (188 loc) 4.83 kB
var process = require('process') , path = require('path') , fs = require('fs') var language = require('cssauron-falafel') , concat = require('concat-stream') , colors = require('ansicolors') , optimist = require('optimist') , globals = require('./globals') , falafel = require('falafel') var lookup = optimist.argv._[optimist.argv._.length - 1] , target = (optimist.argv._ || [])[0] , cwd = process.cwd() , output , input if(lookup === target) { lookup = [] } else { lookup = lookup.split('.') } if(!target) { process.exit(1) } if(target !== '-') { target = target[0] === '/' ? target : path.join(cwd, target || '') try { input = fs.createReadStream(target).pipe(concat(process_file)) } catch(err) { console.error('not a file') process.exit(1) } } else { process.stdin.pipe(concat(process_file)) if(process.stdin.paused) { process.stdin.resume() } } function process_file(input) { var pos = null input = new Buffer('function module() { ' + input + ' }') if(optimist.argv.position) { pos = line_col_to_idx.apply( null , (optimist.argv.position + ',1').split(',').map(Number) ) } try { falafel(input + '', { ranges: true , ecmaVersion: 6 }, require('./index')(globals, optimist.attach, done)) } finally { } function done(last) { var exit_code = handle_globals(last) if(pos) { handle_position(pos, [last]) } return process.exit(exit_code) } function handle_globals(top_level) { var uses = top_level.uses , explicit = 0 , default_fmt , node , use , fmt var formats = { 'explicit': colors.red , 'implicit': colors.yellow } default_fmt = colors.yellow for(var i = 0, len = uses.length; i < len; ++i) { use = uses[i] for(var j = 0, jlen = use.nodes.length; j < jlen; ++j) { node = use.nodes[j] fmt = formats[node.kind] || default_fmt console.log( colors.cyan( 'L' + pad( idx_to_line_col(node.node.range[0]).line + '' , 6 ) ) , pad(use.name, 30) + fmt(pad(node.kind)) ) if(uses[i].nodes[j].kind === 'explicit') { ++explicit } } } return explicit } function handle_position(pos, scopes) { var chain = [] , current for(var i = 0, len = scopes.length; i < len; ++i) { if(scopes[i].scope.range[0] < pos && scopes[i].scope.range[1] > pos) { chain.push(scopes[i]) scopes = scopes[i].children i = -1 len = scopes.length } } while(chain.length > 1) { current = chain.pop() print(current, chain.length) } } function print(scope, idx) { var from = idx_to_line_col(scope.scope.range[0]) , to = idx_to_line_col(scope.scope.range[1]) , name name = scope.scope.type.replace(/([A-Z]{1})/g, function(a, m) { return ' ' + m.toLowerCase() }).slice(1) if(scope.scope.id) { name += ': ' + scope.scope.id.name } if(idx === 1) { name = 'program' } name = colors.yellow('<' + name + '>') + ' from ' + from + ' to ' + to console.log(name) for(var i = 0, len = scope.vars.length; i < len; ++i) { console.log( colors.green('+ ') + colors.cyan(pad( 'L' + idx_to_line_col( scope.vars[i].nodes[0].node.range[0] ).line + '' , 6 )) , pad(scope.vars[i].name, 24) , 'used' , (scope.vars[i].nodes.length - 1) + ' time(s)' ) } for(var i = 0, len = scope.uses.length; i < len; ++i) { console.log( colors.magenta('* ') + colors.cyan(pad( 'L' + idx_to_line_col( scope.uses[i].nodes[0].node.range[0] ).line + '' , 6 )) , pad(scope.uses[i].name, 24) ) } } function pad(s, n) { while(s.length < n) { s = s + ' ' } return s.slice(0, n) } function line_col_to_idx(line, col) { line -= 1 col -= 1 for(var i = 0, len = input.length; i < len; ++i) { if(line && input[i] === 0xA) { --line } if(!line) { if(!col) { return i } --col } } return null } function idx_to_line_col(idx) { var columns = 0 , lines = 0 for(var i = 0, len = idx; i < len; ++i) { ++columns if(input[i] === 0xA) { ++lines columns = 0 } } return {line: 1 + lines, col: columns + 1, toString: str} function str() { return colors.cyan('L' + this.line + ':' + this.col) } } }