Source: unparam.js

 * @module unparam
'use strict';
/*eslint-disable no-caller*/
module.exports = function(fs,path,files,noop,util,Transform,Writable,proc,cons){

    // Global declarations for these, they can get set globally every time in case something gets messed up
    var unparamReadFile, writeStream;
     * Transform stream to write a json array.
     * @constructor
     * @param {WritableStream} actualWriteStream - The underlying writable stream
     * @param {object} options - The other options
     * @returns {JsonWriter} An instance of JsonWriter
    function JsonWriter(actualWriteStream,options){
        this._dest = actualWriteStream;
        this._start = '[\n    ';,options);
        this._writableState.objectMode = true;
        this._readableState.objectMode = false;
    JsonWriter.prototype._transform = function(chunk,encoding,callback){
        // We don't need no fancy ifs!
        // Just redefine the _start after we write, idempotence is great!
        this._start = ',\n    ';
     * The unparam object. If called without new, it will behave as if its unparam function had been called.
     * @constructor
     * @param {object} options The options object
     * @param {boolean} options.trace Whether to turn on tracing
     * @param {boolean} options.readFiles Whether to read the source files and grab the line of the calls
     * @param {string|Writable} options.writeFile The filename to write with the report, or a writable stream
     * @returns {Unparam#unparam} This instance's unparam reporter function
    function Unparam(options){

        // Guard against dereferencing a null object
        options = options || {};
        // DANGER: Don't use `this` before we check if we are instanceof Unparam
        unparamReadFile = options.readFiles || proc.env.UNPARAM_READ_FILES;
        var actualWriteStream;
        var unparamWriteFile = options.writeFile || proc.env.UNPARAM_WRITE_FILE;
            // Open in append mode so we can write to it properly on exit
            if(typeof unparamWriteFile === 'string'){
                actualWriteStream = fs.createWriteStream(path.resolve(__dirname,unparamWriteFile));
            } else if(unparamWriteFile instanceof Writable){
                actualWriteStream = unparamWriteFile;
            } else {
                // Do nothing
                return noop;
            writeStream = new JsonWriter(actualWriteStream);
                /*istanbul ignore next: Impossible to test ATM*/

                    // REALLY terrible hack because we can't write to the stream
                    // at this point, but there's no way to hook sooner because
                    // we need to capture all calls to unparam until the end of the
                    // process execution. Must writeSync to get the proper json
                    // output in the file. We can assume that since this is on process
                    // exit event, the buffers have been flushed and the file is safe
                    // to write, especially since the event loop is dead. Once node v0.12
                    // comes out, we should be able to hook process.on('beforeExit')

                    /*eslint-disable no-sync*/
                    /*eslint-enable no-sync*/
        } else {
            writeStream = {write:noop};
        if(!(this instanceof Unparam)){
                return noop();
            // Use legacy behavior because they did not make a new Unparam instance
            var opts = {callStackDepth:2,trace:true,readFiles:unparamReadFile,writeStream:writeStream};
            var up = new Unparam(opts);
            return up();
        if(!proc.env.UNPARAM_TRACE && !options.trace){
            // Don't do anything, use legacy behavior
            return noop;
        proc.env.UNPARAM_TRACE = proc.env.UNPARAM_TRACE || options.trace;
        this.trace = options.trace;
        this.readFiles = options.readFiles;
        this.writeStream = options.writeStream || writeStream;
        // callStackDepth will never be 0, so we can safely use || here
        this.callStackDepth = options.callStackDepth || 1;
        return this.unparam.bind(this);
     * Prepares and captures a stack trace, which will give the line number, filename, column, and optionally the actual source code
     * @returns {void}
    Unparam.prototype.unparam = function(){
        var obj;
        unparamReadFile = this.readFiles;
        var orig = Error.prepareStackTrace;
        Error.prepareStackTrace = function(_,stack){ return stack; };
            throw new Error();
        } catch(e){
            var stack = e.stack;
            var call = stack[this.callStackDepth];
            var lineNum = call.getLineNumber();
            var filename = call.getFileName();
            var column = call.getColumnNumber();
            var line = '';
            obj = {column:column,lineNumber:lineNum,filename:filename};
                /*eslint-disable no-sync*/
                var sourcelines = fs.readFileSync(filename,'utf8');
                /*eslint-enable no-sync*/
                line = sourcelines.split('\n')[lineNum-1].slice(column-1);
       = line;
            files[filename] = files[filename] || [];
        Error.prepareStackTrace = orig;
        /*istanbul ignore else: don't need to cover noops*/
        if(proc.env.UNPARAM_TRACE && !proc.env.UNPARAM_WRITE_FILE){
    return Unparam;