Fix indentation for JSDoc comments (#2470)

* Fix TypeScript comment snapshot

* Add failing test for TypeScript method comments

* Remove trailing space in comment

* Add snapshot for comment with many lines

* Add TODO marking potential location for comment re-indentation

* Update snapshot

* Indent comments based on the parent node

* Only adjust indentation if the comment looks like a JSDoc comment

* Only strip leading spaces when adjusting comment indentation

* Update snapshot

* Add test to show incorrect indentation based on parent node

* Update snapshot

* Update snapshot

* Update comment indentation to not rely on the parent node

* Extract code for getting the indent size

* Add test where the parent indentation changes as well

* Fix lint warning regarding lexical declarations within case block

* Update lockfile

* Update snapshot

* Add test case for block comment inside of a method

* Replace spread operator with `concat`

* Use `align` instead of `addAlignmentToDoc`

* Add test for mismatched indentation within JSDoc comment

* Always add a leading space to subsequent lines in a JSDoc comment

* Refactor JSDoc comment printing into a separate function

* Remove unneeded `align`

* Replace `forEach` with `map` for better style

* Only `trimLeft` when the end comment token is on the last line of the comment

* Remove unneeded `docBuilders`

* Add tests for JSDoc comments in JSX

* Update snapshots
master
Marshall Bowers 2017-10-08 05:34:24 -04:00 committed by Lucas Azzola
parent 67e4b7db04
commit 445f51709e
12 changed files with 275 additions and 28 deletions

View File

@ -919,8 +919,13 @@ function printComment(commentPath, options) {
case "Comment":
return "#" + comment.value.trimRight();
case "CommentBlock":
case "Block":
case "Block": {
if (isJsDocComment(comment)) {
return printJsDocComment(comment);
}
return "/*" + comment.value + "*/";
}
case "CommentLine":
case "Line":
// Print shebangs with the proper comment characters
@ -933,6 +938,31 @@ function printComment(commentPath, options) {
}
}
function isJsDocComment(comment) {
const lines = comment.value.split("\n");
return (
lines.length > 1 &&
lines.slice(0, lines.length - 1).every(line => line.trim()[0] === "*")
);
}
function printJsDocComment(comment) {
const lines = comment.value.split("\n");
return concat([
"/*",
join(
hardline,
lines.map(
(line, index) =>
(index > 0 ? " " : "") +
(index < lines.length - 1 ? line.trim() : line.trimLeft())
)
),
"*/"
]);
}
function findExpressionIndexForComment(quasis, comment) {
const startPos = locStart(comment) - 1;

View File

@ -1907,19 +1907,17 @@ function genericPrintNoParens(path, options, print, args) {
// quasi literal), therefore we want to indent the JavaScript
// expression inside at the beginning of ${ instead of the beginning
// of the `.
let size = 0;
const value = childPath.getValue().value.raw;
const index = value.lastIndexOf("\n");
const tabWidth = options.tabWidth;
if (index !== -1) {
size = util.getAlignmentSize(
// All the leading whitespaces
value.slice(index + 1).match(/^[ \t]*/)[0],
tabWidth
);
}
const indentSize = util.getIndentSize(
childPath.getValue().value.raw,
tabWidth
);
const aligned = addAlignmentToDoc(expressions[i], size, tabWidth);
const aligned = addAlignmentToDoc(
expressions[i],
indentSize,
tabWidth
);
parts.push("${", aligned, lineSuffixBoundary, "}");
}

View File

@ -475,6 +475,19 @@ function getAlignmentSize(value, tabWidth, startIndex) {
return size;
}
function getIndentSize(value, tabWidth) {
const lastNewlineIndex = value.lastIndexOf("\n");
if (lastNewlineIndex === -1) {
return 0;
}
return getAlignmentSize(
// All the leading whitespaces
value.slice(lastNewlineIndex + 1).match(/^[ \t]*/)[0],
tabWidth
);
}
function printString(raw, options, isDirectiveLiteral) {
// `rawContent` is the string exactly like it appeared in the input source
// code, without its enclosing quotes.
@ -618,6 +631,7 @@ module.exports = {
isBlockComment,
hasClosureCompilerTypeCastComment,
getAlignmentSize,
getIndentSize,
printString,
printNumber
};

View File

@ -816,6 +816,28 @@ exports[`jsx.js 1`] = `
<div>{/*<div> Some very v ery very very long line to break line width limit </div>*/}</div>;
<div>
{/**
* JSDoc-y comment in JSX. I wonder what will happen to it?
*/}
</div>;
<div>
{
/**
* Another JSDoc comment in JSX.
*/
}
</div>;
<div
/**
* Handles clicks.
*/
onClick={() => {}}>
</div>;
<Wrapper>
{}
<Component />
@ -875,6 +897,25 @@ exports[`jsx.js 1`] = `
{/*<div> Some very v ery very very long line to break line width limit </div>*/}
</div>;
<div>
{/**
* JSDoc-y comment in JSX. I wonder what will happen to it?
*/}
</div>;
<div>
{/**
* Another JSDoc comment in JSX.
*/}
</div>;
<div
/**
* Handles clicks.
*/
onClick={() => {}}
/>;
<Wrapper>
{}
<Component />

View File

@ -67,6 +67,28 @@
<div>{/*<div> Some very v ery very very long line to break line width limit </div>*/}</div>;
<div>
{/**
* JSDoc-y comment in JSX. I wonder what will happen to it?
*/}
</div>;
<div>
{
/**
* Another JSDoc comment in JSX.
*/
}
</div>;
<div
/**
* Handles clicks.
*/
onClick={() => {}}>
</div>;
<Wrapper>
{}
<Component />

View File

@ -11,8 +11,8 @@ class x {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class x {
/**
* Set of default settings to be applied to model fetch calls in DAO layer.
*/
* Set of default settings to be applied to model fetch calls in DAO layer.
*/
static get defaultSettings() {}
}

View File

@ -212,7 +212,7 @@ exports[`reach.js 1`] = `
/**
* like class and function values, any-typed values may be used in
* type annotations. Here we test propagation of any through the
* annotation - without it, the body of the if will be unreachable
* annotation - without it, the body of the if will be unreachable
*/
type AsyncRequest = any;
@ -226,7 +226,7 @@ function foo(o: ?AsyncRequest) {
/**
* like class and function values, any-typed values may be used in
* type annotations. Here we test propagation of any through the
* annotation - without it, the body of the if will be unreachable
* annotation - without it, the body of the if will be unreachable
*/
type AsyncRequest = any;

View File

@ -1,7 +1,7 @@
/**
* like class and function values, any-typed values may be used in
* type annotations. Here we test propagation of any through the
* annotation - without it, the body of the if will be unreachable
* annotation - without it, the body of the if will be unreachable
*/
type AsyncRequest = any;

View File

@ -38,7 +38,7 @@ function foo(bar) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/**
* Here lie words above pragmas
*
*
* @flow
* @format
*/

View File

@ -12,10 +12,10 @@ abstract class AbstractRule {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
abstract class AbstractRule {
/**
* @deprecated
* Failures will be filtered based on \`tslint:disable\` comments by tslint.
* This method now does nothing.
*/
* @deprecated
* Failures will be filtered based on \`tslint:disable\` comments by tslint.
* This method now does nothing.
*/
filterFailures() {}
}
@ -116,6 +116,102 @@ export type WrappedFormUtils = {
`;
exports[`methods.ts 1`] = `
export class Point {
/**
* Does something.
*/
foo() {}
/**
* Does something else.
*/
bar() {}
/**
* Does
* something
* much
* better
* than
* the
* rest.
*/
baz() {}
/**
* Buzz-Fizz.
* Note: This is indented too far.
*/
fizzBuzz() {}
/**
* Turns the given string into pig-latin.
*/
pigLatinize(value: string) {
/**
* This is a block comment inside of a method.
*/
}
/**
* One
* Two
* Three
* Four
*/
mismatchedIndentation() {}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
export class Point {
/**
* Does something.
*/
foo() {}
/**
* Does something else.
*/
bar() {}
/**
* Does
* something
* much
* better
* than
* the
* rest.
*/
baz() {}
/**
* Buzz-Fizz.
* Note: This is indented too far.
*/
fizzBuzz() {}
/**
* Turns the given string into pig-latin.
*/
pigLatinize(value: string) {
/**
* This is a block comment inside of a method.
*/
}
/**
* One
* Two
* Three
* Four
*/
mismatchedIndentation() {}
}
`;
exports[`type-parameters.ts 1`] = `
functionName<A /* A comment */>();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,46 @@
export class Point {
/**
* Does something.
*/
foo() {}
/**
* Does something else.
*/
bar() {}
/**
* Does
* something
* much
* better
* than
* the
* rest.
*/
baz() {}
/**
* Buzz-Fizz.
* Note: This is indented too far.
*/
fizzBuzz() {}
/**
* Turns the given string into pig-latin.
*/
pigLatinize(value: string) {
/**
* This is a block comment inside of a method.
*/
}
/**
* One
* Two
* Three
* Four
*/
mismatchedIndentation() {}
}

View File

@ -2398,6 +2398,12 @@ jest-diff@^21.2.1:
jest-get-type "^21.2.0"
pretty-format "^21.2.1"
jest-docblock@21.3.0-beta.1:
version "21.3.0-beta.1"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.3.0-beta.1.tgz#f264d50ba1fc93cda8ef3ffcd530cef86b332c3d"
dependencies:
detect-newline "^2.1.0"
jest-docblock@^20.0.1:
version "20.0.3"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-20.0.3.tgz#17bea984342cc33d83c50fbe1545ea0efaa44712"
@ -2406,12 +2412,6 @@ jest-docblock@^21.2.0:
version "21.2.0"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.2.0.tgz#51529c3b30d5fd159da60c27ceedc195faf8d414"
jest-docblock@^21.3.0-beta.1:
version "21.3.0-beta.1"
resolved "https://registry.yarnpkg.com/jest-docblock/-/jest-docblock-21.3.0-beta.1.tgz#f264d50ba1fc93cda8ef3ffcd530cef86b332c3d"
dependencies:
detect-newline "^2.1.0"
jest-environment-jsdom@^21.2.1:
version "21.2.1"
resolved "https://registry.yarnpkg.com/jest-environment-jsdom/-/jest-environment-jsdom-21.2.1.tgz#38d9980c8259b2a608ec232deee6289a60d9d5b4"