Code coverage report for lib/parsers/javascript.js

Statements: 100% (25 / 25)      Branches: 90% (9 / 10)      Functions: 100% (4 / 4)      Lines: 100% (25 / 25)      Ignored: none     

All files » lib/parsers/ » javascript.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87    35                         35 229 229             228   35 684               35 411           411 411 314 314     240         240 240           74         314       28326       28326         228 228 228   228     35  
'use strict';
 
var babel = require('babel-core'),
  types = require('ast-types'),
  extend = require('extend'),
  isJSDocComment = require('../../lib/is_jsdoc_comment'),
  parse = require('../../lib/parse');
 
/**
 * Receives a module-dep item,
 * reads the file, parses the JavaScript, and parses the JSDoc.
 *
 * @param {Object} data a chunk of data provided by module-deps
 * @return {Array<Object>} an array of parsed comments
 */
function parseJavaScript(data) {
  var results = [];
  var ast = babel.parse(data.source, {
    code: false,
    stage: 0,
    locations: true,
    ranges: true
  });
 
  var visited = {};
 
  function walkComments(ast, type, includeContext) {
    types.visit(ast, {
      visitNode: function (path) {
        /**
         * Parse a comment with doctrine and decorate the result with file position and code context.
         *
         * @param {Object} comment the current state of the parsed JSDoc comment
         * @return {undefined} this emits data
         */
        function parseComment(comment) {
          var context = {
            loc: extend({}, path.value.loc),
            file: data.file
          };
          // Avoid visiting the same comment twice as a leading
          // and trailing node
          var key = JSON.stringify(comment.loc);
          if (!visited[key]) {
            visited[key] = true;
            if (includeContext) {
              // This is non-enumerable so that it doesn't get stringified in
              // output; e.g. by the documentation binary.
              Object.defineProperty(context, 'ast', {
                enumerable: false,
                value: path
              });
 
              Eif (path.parent && path.parent.node) {
                context.code = data.source.substring
                  .apply(data.source, path.parent.node.range);
              }
            } else {
              // Avoid the invariant of a comment with no AST by providing
              // an empty one.
              Object.defineProperty(context, 'ast', {
                enumerable: false,
                value: {}
              });
            }
            results.push(parse(comment.value, comment.loc, context));
          }
        }
 
        (path.value[type] || [])
          .filter(isJSDocComment)
          .forEach(parseComment);
 
        this.traverse(path);
      }
    });
  }
 
  walkComments(ast, 'leadingComments', true);
  walkComments(ast, 'innerComments', false);
  walkComments(ast, 'trailingComments', false);
 
  return results;
}
 
module.exports = parseJavaScript;