John Cashew
John Cashew

Reputation: 1084

How to address JSHint warnings that functions are not defined when there are many externally defined functions

This often asked question is usually answered by stating that each JavaScript file should configure the externally defined globals that it uses in the JSHint configuration.

In my case I have library files that define several hundred functions. I have many other files that call functions from those libraries.

It would be difficult to maintain copying and pasting the name of every library function into the JSHint configuration.

Is there a more maintainable way of addressing this warning?

  1. Is there some method of combining a file with its library files before linting them?
  2. Is there an alternate tool which addresses this problem?
  3. Is there an approach for creating or using JavaScript libraries that eliminates the need to answer this question?

Ideally any answers to this questions will work with an Eclipse plug-in.

Upvotes: 3

Views: 1014

Answers (1)

Filip Dupanović
Filip Dupanović

Reputation: 33670

You should check the globals option.

In the case that there are scores of globals which cannot be manually managed, the best approach would be to either namespace them or to automate the authoring of the JSHint configuration.

Namespacing

With namespacing, akin to having classes with static methods, you can group related globals as references on a single object. I believe that in modern compilers you should expect to see some performance improvements when resolving the associated references on said objects.

var gardening = (function () {
   var exports = {};
   exports.water = function () {};

   function till () {};
   exports.till = till;

   return exports;
})();

var debug = {
   prettyPrint: function (obj) {}
   inspect: function () {}
};

So, as opposed to having a blob of several dozen shoulder-to-shoulder globals, you can extract a few objects under which to group the references. Creating such hierarchies supports the brain's aptitude to construct tree-like resolutions for functions which are related in their purpose.

Dynamically authoring your JSHint configuration

If you already have some task runner implemented for your project (and you probably do), then it wouldn't hurt to add some custom task for aggregating globals from source files when these can be counted in scores and cannot be reasonably managed with a manual approach.

#!/usr/bin/env node
// ./task.js
var fs = require('fs');

// Some pre-defined JSHint options
var jsHintOptions = {
   maxerr: 10,
   bitwise: true,
   globals: {
       foo: true,
       bar: false
   }
}

var cmd = process.argv[2];
if (cmd === 'author-jshintrc') authorJsHintRc();

// Hammer time!
function authorJsHintRc() {
    var globals = [];
    // Some fancy regular expression which can match
    // the globals from your sources
    var reMatchGlobal = /^\s+function\s([\w\d_]+)/gm;

    var extractGlobals = function (name) {
        var contents = fs.readFileSync(name).toString();
        var matches = contents.match(reMatchGlobal);
        globals.push.apply(globals, matches);
    }

    var registerGlobal = function (global) {
        jsHintOptions.globals[global] = false;
    }

    // These are our problematic source files which contain
    // too many globals to specify manually
    [
        'path/to/foo.js', 
        'path/to/bar.js'
    ].forEach(extractGlobals);

    // Extend the jsHintOptions with the dynamically resolved globals
    globals.forEach(registerGlobal);

    // Author the project's .jshintrc
    fs.writeFileSync('.jshintrc', JSON.stringify(jsHintOptions));
}

Ideally, dropping or extending the .jshintrc in your project root should mean these options are introspected by the Eclipse JSHint plugin and the project JSHint errors should immediately go away.

Upvotes: 2

Related Questions