Skip to content
Permalink
Browse files

Fix: Jsdoc comment for multi-line function expressions (fixes #4889)

  • Loading branch information...
gyandeeps committed Jan 8, 2016
1 parent 3d91e40 commit e5e06f817c5e4a50fbe0f1401e818ccd5d2fb701
Showing with 149 additions and 7 deletions.
  1. +6 −7 lib/util/source-code.js
  2. +53 −0 tests/lib/rules/valid-jsdoc.js
  3. +90 −0 tests/lib/util/source-code.js
@@ -216,29 +216,28 @@ SourceCode.prototype = {
*/
getJSDocComment: function(node) {

var parent = node.parent,
line = node.loc.start.line;
var parent = node.parent;

switch (node.type) {
case "ClassDeclaration":
case "FunctionDeclaration":
if (looksLikeExport(parent)) {
return findJSDocComment(parent.leadingComments, line);
return findJSDocComment(parent.leadingComments, parent.loc.start.line);
}
return findJSDocComment(node.leadingComments, line);
return findJSDocComment(node.leadingComments, node.loc.start.line);

case "ClassExpression":
return findJSDocComment(parent.parent.leadingComments, line);
return findJSDocComment(parent.parent.leadingComments, parent.parent.loc.start.line);

case "ArrowFunctionExpression":
case "FunctionExpression":

if (parent.type !== "CallExpression" && parent.type !== "NewExpression") {
while (parent && !parent.leadingComments && !/Function/.test(parent.type)) {
while (parent && !parent.leadingComments && !/Function/.test(parent.type) && parent.type !== "MethodDefinition") {
parent = parent.parent;
}

return parent && (parent.type !== "FunctionDeclaration") ? findJSDocComment(parent.leadingComments, line) : null;
return parent && (parent.type !== "FunctionDeclaration") ? findJSDocComment(parent.leadingComments, parent.loc.start.line) : null;
}

// falls through
@@ -325,6 +325,59 @@ ruleTester.run("valid-jsdoc", rule, {
type: "Block"
}]
},
{
code: "/**\n* Foo\n* @param {string} p \n*/\nvar foo = function(){}",
errors: [{
message: "Missing JSDoc parameter description for 'p'.",
type: "Block"
}, {
message: "Missing JSDoc @returns for function.",
type: "Block"
}]
},
{
code: "/**\n* Foo\n* @param {string} p \n*/\nvar foo = \nfunction(){}",
errors: [{
message: "Missing JSDoc parameter description for 'p'.",
type: "Block"
}, {
message: "Missing JSDoc @returns for function.",
type: "Block"
}]
},
{
code:
"/**\n" +
" * Description for a\n" +
" */\n" +
"var A = \n" +
" class {\n" +
" /**\n" +
" * Description for constructor.\n" +
" * @param {object[]} xs - xs\n" +
" */\n" +
" constructor(xs) {\n" +
" this.a = xs;" +
" }\n" +
"};",
options: [{
requireReturn: true,
"matchDescription": "^[A-Z][A-Za-z0-9\\s]*[.]$"
}],
errors: [
{
message: "JSDoc description does not satisfy the regex pattern.",
type: "Block"
},
{
message: "Missing JSDoc @returns for function.",
type: "Block"
}
],
parserOptions: {
ecmaVersion: 6
}
},
{
code: "/**\n* Foo\n* @returns {string} \n*/\nfunction foo(){}",
errors: [{
@@ -655,6 +655,96 @@ describe("SourceCode", function() {
assert.isTrue(spy.calledOnce, "Event handler should be called.");
});

it("should not get JSDoc comment for class method even if the class has jsdoc present", function() {

var code = [
"/** Merges two objects together.*/",
"var A = class {",
" constructor(xs) {}",
"};"
].join("\n");

/**
* Check jsdoc presence
* @param {ASTNode} node not to check
* @returns {void}
* @private
*/
function assertJSDoc(node) {
var sourceCode = eslint.getSourceCode();
var jsdoc = sourceCode.getJSDocComment(node);
assert.isNull(jsdoc);
}

var spy = sandbox.spy(assertJSDoc);

eslint.on("FunctionExpression", spy);
eslint.verify(code, { rules: {}, parserOptions: { ecmaVersion: 6 }}, filename, true);
assert.isTrue(spy.calledOnce, "Event handler should be called.");
});

it("should get JSDoc comment for function expression even if function has blank lines on top", function() {

var code = [
"/** Merges two objects together.*/",
"var A = ",
" ",
" ",
" ",
" function() {",
"};"
].join("\n");

/**
* Check jsdoc presence
* @param {ASTNode} node not to check
* @returns {void}
* @private
*/
function assertJSDoc(node) {
var sourceCode = eslint.getSourceCode();
var jsdoc = sourceCode.getJSDocComment(node);
assert.equal(jsdoc.type, "Block");
assert.equal(jsdoc.value, "* Merges two objects together.");
}

var spy = sandbox.spy(assertJSDoc);

eslint.on("FunctionExpression", spy);
eslint.verify(code, { rules: {}, parserOptions: { ecmaVersion: 6 }}, filename, true);
assert.isTrue(spy.calledOnce, "Event handler should be called.");
});

it("should not get JSDoc comment for function declaration when the function has blank lines on top", function() {

var code = [
"/** Merges two objects together.*/",
" ",
" ",
" ",
"function test() {",
"};"
].join("\n");

/**
* Check jsdoc presence
* @param {ASTNode} node not to check
* @returns {void}
* @private
*/
function assertJSDoc(node) {
var sourceCode = eslint.getSourceCode();
var jsdoc = sourceCode.getJSDocComment(node);
assert.isNull(jsdoc);
}

var spy = sandbox.spy(assertJSDoc);

eslint.on("FunctionDeclaration", spy);
eslint.verify(code, { rules: {}, parserOptions: { ecmaVersion: 6 }}, filename, true);
assert.isTrue(spy.calledOnce, "Event handler should be called.");
});

});

describe("getComments()", function() {

0 comments on commit e5e06f8

Please sign in to comment.
You can’t perform that action at this time.