All files / src/handlers componentDocblockHandler.js

95.24% Statements 20/21
88.46% Branches 23/26
100% Functions 2/2
95.24% Lines 20/21
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                                  2x     51x 51x                     88x   88x 88x 90x   88x   88x   34x   88x   88x     15x       88x     51x 51x 51x   51x 17x     88x    
/*
 * Copyright (c) 2015, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @flow
 *
 */
 
import type Documentation from '../Documentation';
 
import recast from 'recast';
import {getDocblock} from '../utils/docblock';
 
var {types: {namedTypes: types}} = recast;
 
function isClassDefinition(nodePath) {
  var node = nodePath.node;
  return types.ClassDeclaration.check(node) ||
    types.ClassExpression.check(node);
}
 
/**
 * Finds the nearest block comment before the component definition.
 */
export default function componentDocblockHandler(
  documentation: Documentation,
  path: NodePath
) {
  var description = null;
  // Find parent statement (e.g. var Component = React.createClass(<path>);)
  var searchPath = path;
  while (searchPath && !types.Statement.check(searchPath.node)) {
    searchPath = searchPath.parent;
  }
  Eif (searchPath) {
    // If the parent is an export statement, we have to traverse one more up
    if (types.ExportNamedDeclaration.check(searchPath.parentPath.node) ||
        types.ExportDefaultDeclaration.check(searchPath.parentPath.node)) {
      searchPath = searchPath.parentPath;
    }
    description = getDocblock(searchPath);
  }
  if (description == null && isClassDefinition(path)) {
    // If we have a class declaration or expression, then the comment might be
    // attached to the first decorator instead.
    Iif (path.node.decorators && path.node.decorators.length > 0) {
      description = getDocblock(path.get('decorators', 0));
    }
  }
  if (description == null) {
    // If this is the first statement in the module body, the comment is attached
    // to the program node
    var programPath = searchPath;
    while (programPath && !types.Program.check(programPath.node)) {
      programPath = programPath.parent;
    }
    if (programPath.get('body', 0) === searchPath) {
      description = getDocblock(programPath);
    }
  }
  documentation.set('description', description || '');
}