Created
March 23, 2015 20:09
-
-
Save venning/55173b5e5f80aea39995 to your computer and use it in GitHub Desktop.
lodash: automated test for iteratee/predicate in documentation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env node | |
/* | |
* much of this was taken from: | |
* https://bitbucket.org/ariya/missing-doc/src/master/missing-doc.js | |
*/ | |
'use strict'; | |
var _ = require('lodash'), | |
fs = require('fs'), | |
esprima = require('esprima'), | |
estraverse = require('estraverse'), | |
doctrine = require('doctrine'), | |
indentString = require('indent-string'); | |
//////////////////////// | |
//// MAIN ROUTINE //// | |
//////////////////////// | |
// globals because I'm lazy | |
var total = 0, | |
successes = 0; | |
// lodash source file as command-line argument | |
buildAndWalkTree(process.argv[2]); | |
console.log('\n' + successes + ' out of ' + total + ' examples succeeeded.') | |
/////////////////// | |
//// WORKERS //// | |
/////////////////// | |
function buildAndWalkTree (filename) { | |
var content, tree; | |
try { | |
content = fs.readFileSync(filename, 'utf-8'); | |
tree = esprima.parse(content, { attachComment: true, loc: true }); | |
// walk the tree | |
estraverse.traverse(tree, { enter: workNode }); | |
} catch (e) { | |
console.error(e.toString()); | |
process.exit(1); | |
} | |
} | |
function workNode (node) { | |
if (node.type === 'Identifier') { | |
// just a duplicate from something else | |
return; | |
} | |
if (node.leadingComments && node.id && node.id.leadingComments) { | |
// this should never happen, but it's worth getting a warning if it does | |
console.error(node.id.name + ' has leadingComments in two places in the AST'); | |
process.exit(1); | |
} | |
var leadingComments = node.leadingComments || (node.id && node.id.leadingComments); | |
var name = node.name || (node.id && node.id.name); | |
_.forEach(leadingComments, _.partial(workComment, name)); | |
} | |
function workComment (name, comment) { | |
var doctrineOpts = { | |
unwrap: true, // pulls out the leading `*`s | |
recoverable: true, // allows for badly-formed JSDoc | |
sloppy: true // correctly parses square-bracketed optional parameters | |
}; | |
var data = doctrine.parse(comment.value, doctrineOpts); | |
// some functions have @name annotations that should take precedence | |
name = _.result(_.find(data.tags, { title: 'name' }), 'name') || name; | |
// do the work | |
var err = checkParams(data); | |
if (err) { | |
console.log(name + '\n' + indentString(err, ' ', 4)); | |
} else { | |
++successes; | |
} | |
++total; | |
} | |
// returns error | |
function checkParams (data) { | |
var desc = data.description; | |
var paramNames = _.pluck(_.where(data.tags, { title: 'param' }), 'name'); | |
var hasIteratee = _.contains(paramNames, 'iteratee'); | |
var hasPredicate = _.contains(paramNames, 'predicate'); | |
// shouldn't happen, but warn if so | |
if (hasIteratee && hasPredicate) { | |
return 'ERROR: BOTH iteratee AND predicate PARAMETERS'; | |
} | |
if (hasIteratee) { | |
if (desc.match(/predicate/i)) { | |
return 'USES iteratee, DESCRIBES predicate'; | |
} | |
} else if (hasPredicate) { | |
if (desc.match(/iteratee/i)) { | |
return 'USES predicate, DESCRIBES iteratee'; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"dependencies": { | |
"lodash": "~3.5.0", | |
"estraverse": "~3.1.0", | |
"esprima": "~2.1.0", | |
"doctrine": "~0.6.4", | |
"indent-string": "~1.2.1" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment