in packages/flow-dev-tools/src/comment/commentMutator.js [189:317]
function addCommentToText(
contents: Buffer,
loc: FlowLoc,
inside: Context,
comments: Array<string>,
ast: any,
startOfLine?: number,
): Buffer {
let startOffset;
let start;
if (startOfLine == null) {
startOffset = loc.start.offset;
start = findStartOfLine(contents, startOffset);
} else {
start = startOfLine;
startOffset = startOfLine;
}
const endOfLine = findEndOfLine(contents, startOffset);
let line = contents.toString('utf8', start, endOfLine);
const inJSX = inside === JSX_FRAGMENT || inside === JSX;
if (inside === NORMAL) {
return insertCommentToText(
contents,
start,
formatComment(comments, line, {jsx: false}).join('\n') + '\n',
);
} else if (inJSX && ast.type === 'JSXElement') {
return insertCommentToText(
contents,
start,
formatComment(comments, line, {jsx: true}).join('\n') + '\n',
);
} else if (
inside === TEMPLATE ||
(inJSX && ast.type === 'JSXExpressionContainer')
) {
/* Ok, so we have something like
*
* <jsx>
* {10 * 'hello'}
* <jsx>
*
* We need to stick the comment inside the expression container.
* So the above example turns into
*
* <jsx>
* {
* // Comment
* 10 * 'hello'}
* <jsx>
*
* Same thing if we have something like
*
* var str = `hello
* ${10 * 'hello'}
* `;
*
* We need to stick the comment inside of the template element. So the
* above example turns into
*
* var str = `hello
* ${
* // Comment
* 10 * 'hello'}
* `;
*/
const start_col = inJSX ? ast.loc.start.column + 1 : ast.loc.start.column;
const part1 = line.substr(0, start_col);
const match = part1.match(/^ */);
const padding = match ? match[0] + ' ' : ' ';
const part2 = padding + line.substr(start_col);
const newCode = []
// $FlowFixMe unsealed object but should just be {||}
.concat([part1], formatComment(comments, part2, {}), [part2])
.join('\n');
return Buffer.concat([
contents.slice(0, start),
Buffer.from(newCode),
contents.slice(endOfLine),
]);
} else if (inJSX && ast.type === 'JSXText') {
/* Ignore the case where the error's loc starts after the last non-whitespace
* character of the line. This can occur when an error's loc spans the
* children of a JSX element. We cannot safely add a comment to the line
* before the error's loc, as it may be contained within a JSXOpeningElement.
*
* Loc
* |
* v
* <jsx>
* JSXElement, JSXExpressionContainer, or JSXText here...
* <jsx>
*/
let firstNonWhitespaceCharacter = startOffset;
let atEndOfLine = true;
while (firstNonWhitespaceCharacter < contents.length) {
if (
bufferCharAt(contents, firstNonWhitespaceCharacter).match(newlineRegex)
) {
break;
} else if (
bufferCharAt(contents, firstNonWhitespaceCharacter).match(edible)
) {
firstNonWhitespaceCharacter++;
} else {
atEndOfLine = false;
break;
}
}
if (atEndOfLine) {
return contents;
}
/*
* Otherwise add an expression container above the text with our comment.
*
* <jsx>
* {// Comment}
* JSX Text Here
* <jsx>
*/
return insertCommentToText(
contents,
start,
formatComment(comments, line, {jsx: true}).join('\n') + '\n',
);
}
return contents;
}