Split out location extraction into plugin config (#3777)
* Split out location extraction into plugin config * Reduce set of exported function, rebase to current master * Pass custom locStart/locEnd fn's directly to affected methods * (wip) always use locStart/locEnd from plugin * Convert graphql implementation * Convert HTML implementation * (wip) convert JS implementation * Remove unused variables * Continue conversion of JS implementation * Replace "util.locStart" with direct call to "options.locStart" * Remove util closure * Add unit test for structure of shared util * Fix linting error, simplify locStart/End implementationsmaster
parent
7b2349dcd2
commit
fac08034e7
32
index.js
32
index.js
|
@ -4,7 +4,7 @@ const docblock = require("jest-docblock");
|
|||
|
||||
const version = require("./package.json").version;
|
||||
|
||||
const util = require("./src/common/util");
|
||||
const privateUtil = require("./src/common/util");
|
||||
const getSupportInfo = require("./src/common/support").getSupportInfo;
|
||||
|
||||
const comments = require("./src/main/comments");
|
||||
|
@ -111,7 +111,7 @@ function formatWithCursor(text, opts, addAlignmentSize) {
|
|||
const cursorNodeAndParents = findNodeAtOffset(ast, opts.cursorOffset, opts);
|
||||
const cursorNode = cursorNodeAndParents.node;
|
||||
if (cursorNode) {
|
||||
cursorOffset = opts.cursorOffset - util.locStart(cursorNode);
|
||||
cursorOffset = opts.cursorOffset - opts.locStart(cursorNode);
|
||||
opts.cursorNode = cursorNode;
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,7 @@ function format(text, opts, addAlignmentSize) {
|
|||
return formatWithCursor(text, opts, addAlignmentSize).formatted;
|
||||
}
|
||||
|
||||
function findSiblingAncestors(startNodeAndParents, endNodeAndParents) {
|
||||
function findSiblingAncestors(startNodeAndParents, endNodeAndParents, opts) {
|
||||
let resultStartNode = startNodeAndParents.node;
|
||||
let resultEndNode = endNodeAndParents.node;
|
||||
|
||||
|
@ -160,7 +160,7 @@ function findSiblingAncestors(startNodeAndParents, endNodeAndParents) {
|
|||
if (
|
||||
endParent.type !== "Program" &&
|
||||
endParent.type !== "File" &&
|
||||
util.locStart(endParent) >= util.locStart(startNodeAndParents.node)
|
||||
opts.locStart(endParent) >= opts.locStart(startNodeAndParents.node)
|
||||
) {
|
||||
resultEndNode = endParent;
|
||||
} else {
|
||||
|
@ -172,7 +172,7 @@ function findSiblingAncestors(startNodeAndParents, endNodeAndParents) {
|
|||
if (
|
||||
startParent.type !== "Program" &&
|
||||
startParent.type !== "File" &&
|
||||
util.locEnd(startParent) <= util.locEnd(endNodeAndParents.node)
|
||||
opts.locEnd(startParent) <= opts.locEnd(endNodeAndParents.node)
|
||||
) {
|
||||
resultStartNode = startParent;
|
||||
} else {
|
||||
|
@ -189,8 +189,8 @@ function findSiblingAncestors(startNodeAndParents, endNodeAndParents) {
|
|||
function findNodeAtOffset(node, offset, options, predicate, parentNodes) {
|
||||
predicate = predicate || (() => true);
|
||||
parentNodes = parentNodes || [];
|
||||
const start = util.locStart(node);
|
||||
const end = util.locEnd(node);
|
||||
const start = options.locStart(node, options.locStart);
|
||||
const end = options.locEnd(node, options.locEnd);
|
||||
if (start <= offset && offset <= end) {
|
||||
for (const childNode of comments.getSortedChildNodes(
|
||||
node,
|
||||
|
@ -335,12 +335,19 @@ function calculateRange(text, opts, ast) {
|
|||
|
||||
const siblingAncestors = findSiblingAncestors(
|
||||
startNodeAndParents,
|
||||
endNodeAndParents
|
||||
endNodeAndParents,
|
||||
opts
|
||||
);
|
||||
const startNode = siblingAncestors.startNode;
|
||||
const endNode = siblingAncestors.endNode;
|
||||
const rangeStart = Math.min(util.locStart(startNode), util.locStart(endNode));
|
||||
const rangeEnd = Math.max(util.locEnd(startNode), util.locEnd(endNode));
|
||||
const rangeStart = Math.min(
|
||||
opts.locStart(startNode, opts.locStart),
|
||||
opts.locStart(endNode, opts.locStart)
|
||||
);
|
||||
const rangeEnd = Math.max(
|
||||
opts.locEnd(startNode, opts.locEnd),
|
||||
opts.locEnd(endNode, opts.locEnd)
|
||||
);
|
||||
|
||||
return {
|
||||
rangeStart: rangeStart,
|
||||
|
@ -367,7 +374,10 @@ function formatRange(text, opts, ast) {
|
|||
);
|
||||
const indentString = text.slice(rangeStart2, rangeStart);
|
||||
|
||||
const alignmentSize = util.getAlignmentSize(indentString, opts.tabWidth);
|
||||
const alignmentSize = privateUtil.getAlignmentSize(
|
||||
indentString,
|
||||
opts.tabWidth
|
||||
);
|
||||
|
||||
const rangeFormatted = format(
|
||||
rangeString,
|
||||
|
|
|
@ -154,7 +154,13 @@ FastPath.prototype.needsParens = function(options) {
|
|||
|
||||
// Closure compiler requires that type casted expressions to be surrounded by
|
||||
// parentheses.
|
||||
if (util.hasClosureCompilerTypeCastComment(options.originalText, node)) {
|
||||
if (
|
||||
util.hasClosureCompilerTypeCastComment(
|
||||
options.originalText,
|
||||
node,
|
||||
options.locEnd
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -486,7 +492,7 @@ FastPath.prototype.needsParens = function(options) {
|
|||
// See corresponding workaround in printer.js case: "Literal"
|
||||
((options.parser !== "typescript" && !parent.directive) ||
|
||||
(options.parser === "typescript" &&
|
||||
options.originalText.substr(util.locStart(node) - 1, 1) === "("))
|
||||
options.originalText.substr(options.locStart(node) - 1, 1) === "("))
|
||||
) {
|
||||
// To avoid becoming a directive
|
||||
const grandParent = this.getParentNode(1);
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
"use strict";
|
||||
|
||||
const util = require("./util");
|
||||
|
||||
function isNextLineEmpty(text, node, options) {
|
||||
return util.isNextLineEmpty(text, node, options.locEnd);
|
||||
}
|
||||
|
||||
function getNextNonSpaceNonCommentCharacterIndex(text, node, options) {
|
||||
return util.getNextNonSpaceNonCommentCharacterIndex(
|
||||
text,
|
||||
node,
|
||||
options.locEnd
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
isNextLineEmpty,
|
||||
isNextLineEmptyAfterIndex: util.isNextLineEmptyAfterIndex,
|
||||
getNextNonSpaceNonCommentCharacterIndex,
|
||||
mapDoc: util.mapDoc,
|
||||
makeString: util.makeString
|
||||
};
|
|
@ -187,7 +187,7 @@ function hasNewlineInRange(text, start, end) {
|
|||
}
|
||||
|
||||
// Note: this function doesn't ignore leading comments unlike isNextLineEmpty
|
||||
function isPreviousLineEmpty(text, node) {
|
||||
function isPreviousLineEmpty(text, node, locStart) {
|
||||
let idx = locStart(node) - 1;
|
||||
idx = skipSpaces(text, idx, { backwards: true });
|
||||
idx = skipNewline(text, idx, { backwards: true });
|
||||
|
@ -211,11 +211,11 @@ function isNextLineEmptyAfterIndex(text, index) {
|
|||
return hasNewline(text, idx);
|
||||
}
|
||||
|
||||
function isNextLineEmpty(text, node) {
|
||||
function isNextLineEmpty(text, node, locEnd) {
|
||||
return isNextLineEmptyAfterIndex(text, locEnd(node));
|
||||
}
|
||||
|
||||
function getNextNonSpaceNonCommentCharacterIndex(text, node) {
|
||||
function getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd) {
|
||||
let oldIdx = null;
|
||||
let idx = locEnd(node);
|
||||
while (idx !== oldIdx) {
|
||||
|
@ -228,8 +228,10 @@ function getNextNonSpaceNonCommentCharacterIndex(text, node) {
|
|||
return idx;
|
||||
}
|
||||
|
||||
function getNextNonSpaceNonCommentCharacter(text, node) {
|
||||
return text.charAt(getNextNonSpaceNonCommentCharacterIndex(text, node));
|
||||
function getNextNonSpaceNonCommentCharacter(text, node, locEnd) {
|
||||
return text.charAt(
|
||||
getNextNonSpaceNonCommentCharacterIndex(text, node, locEnd)
|
||||
);
|
||||
}
|
||||
|
||||
function hasSpaces(text, index, opts) {
|
||||
|
@ -238,65 +240,6 @@ function hasSpaces(text, index, opts) {
|
|||
return idx !== index;
|
||||
}
|
||||
|
||||
function locStart(node) {
|
||||
// Handle nodes with decorators. They should start at the first decorator
|
||||
if (
|
||||
node.declaration &&
|
||||
node.declaration.decorators &&
|
||||
node.declaration.decorators.length > 0
|
||||
) {
|
||||
return locStart(node.declaration.decorators[0]);
|
||||
}
|
||||
if (node.decorators && node.decorators.length > 0) {
|
||||
return locStart(node.decorators[0]);
|
||||
}
|
||||
|
||||
if (node.__location) {
|
||||
return node.__location.startOffset;
|
||||
}
|
||||
if (node.range) {
|
||||
return node.range[0];
|
||||
}
|
||||
if (typeof node.start === "number") {
|
||||
return node.start;
|
||||
}
|
||||
if (node.source) {
|
||||
return lineColumnToIndex(node.source.start, node.source.input.css) - 1;
|
||||
}
|
||||
if (node.loc) {
|
||||
return node.loc.start;
|
||||
}
|
||||
}
|
||||
|
||||
function locEnd(node) {
|
||||
const endNode = node.nodes && getLast(node.nodes);
|
||||
if (endNode && node.source && !node.source.end) {
|
||||
node = endNode;
|
||||
}
|
||||
|
||||
let loc;
|
||||
if (node.range) {
|
||||
loc = node.range[1];
|
||||
} else if (typeof node.end === "number") {
|
||||
loc = node.end;
|
||||
} else if (node.source) {
|
||||
loc = lineColumnToIndex(node.source.end, node.source.input.css);
|
||||
}
|
||||
|
||||
if (node.__location) {
|
||||
return node.__location.endOffset;
|
||||
}
|
||||
if (node.typeAnnotation) {
|
||||
return Math.max(loc, locEnd(node.typeAnnotation));
|
||||
}
|
||||
|
||||
if (node.loc && !loc) {
|
||||
return node.loc.end;
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
// Super inefficient, needs to be cached.
|
||||
function lineColumnToIndex(lineColumn, text) {
|
||||
let index = 0;
|
||||
|
@ -476,7 +419,7 @@ function isBlockComment(comment) {
|
|||
return comment.type === "Block" || comment.type === "CommentBlock";
|
||||
}
|
||||
|
||||
function hasClosureCompilerTypeCastComment(text, node) {
|
||||
function hasClosureCompilerTypeCastComment(text, node, locEnd) {
|
||||
// https://github.com/google/closure-compiler/wiki/Annotating-Types#type-casts
|
||||
// Syntax example: var x = /** @type {string} */ (fruit);
|
||||
return (
|
||||
|
@ -486,7 +429,7 @@ function hasClosureCompilerTypeCastComment(text, node) {
|
|||
comment.leading &&
|
||||
isBlockComment(comment) &&
|
||||
comment.value.match(/^\*\s*@type\s*{[^}]+}\s*$/) &&
|
||||
getNextNonSpaceNonCommentCharacter(text, comment) === "("
|
||||
getNextNonSpaceNonCommentCharacter(text, comment, locEnd) === "("
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -839,8 +782,6 @@ module.exports = {
|
|||
hasNewline,
|
||||
hasNewlineInRange,
|
||||
hasSpaces,
|
||||
locStart,
|
||||
locEnd,
|
||||
setLocStart,
|
||||
setLocEnd,
|
||||
startsWithNoLookaheadToken,
|
||||
|
@ -852,5 +793,7 @@ module.exports = {
|
|||
printString,
|
||||
printNumber,
|
||||
hasIgnoreComment,
|
||||
hasNodeIgnoreComment
|
||||
hasNodeIgnoreComment,
|
||||
lineColumnToIndex,
|
||||
makeString
|
||||
};
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
const printer = require("./printer-postcss");
|
||||
const options = require("./options");
|
||||
const privateUtil = require("../common/util");
|
||||
|
||||
const lineColumnToIndex = privateUtil.lineColumnToIndex;
|
||||
const getLast = privateUtil.getLast;
|
||||
|
||||
// Based on:
|
||||
// https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
|
||||
|
@ -52,7 +56,23 @@ const postcss = {
|
|||
get parse() {
|
||||
return eval("require")("./parser-postcss");
|
||||
},
|
||||
astFormat: "postcss"
|
||||
astFormat: "postcss",
|
||||
locEnd: function(node) {
|
||||
const endNode = node.nodes && getLast(node.nodes);
|
||||
if (endNode && node.source && !node.source.end) {
|
||||
node = endNode;
|
||||
}
|
||||
if (node.source) {
|
||||
return lineColumnToIndex(node.source.end, node.source.input.css);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
locStart: function(node) {
|
||||
if (node.source) {
|
||||
return lineColumnToIndex(node.source.start, node.source.input.css) - 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: switch these to just `postcss` and use `language` instead.
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
"use strict";
|
||||
|
||||
const clean = require("./clean");
|
||||
const util = require("../common/util");
|
||||
const privateUtil = require("../common/util");
|
||||
const sharedUtil = require("../common/util-shared");
|
||||
const doc = require("../doc");
|
||||
const docBuilders = doc.builders;
|
||||
const concat = docBuilders.concat;
|
||||
|
@ -44,8 +45,8 @@ function genericPrint(path, options, print) {
|
|||
return node.raws.content;
|
||||
}
|
||||
const text = options.originalText.slice(
|
||||
util.locStart(node),
|
||||
util.locEnd(node)
|
||||
options.locStart(node),
|
||||
options.locEnd(node)
|
||||
);
|
||||
const rawText = node.raws.text || node.text;
|
||||
// Workaround a bug where the location is off.
|
||||
|
@ -575,7 +576,7 @@ function genericPrint(path, options, print) {
|
|||
return concat([node.value, " "]);
|
||||
}
|
||||
case "value-string": {
|
||||
return util.printString(
|
||||
return privateUtil.printString(
|
||||
node.raws.quote + node.value + node.raws.quote,
|
||||
options
|
||||
);
|
||||
|
@ -691,8 +692,8 @@ function printNodeSequence(path, options, print) {
|
|||
const childNode = pathChild.getValue();
|
||||
parts.push(
|
||||
options.originalText.slice(
|
||||
util.locStart(childNode),
|
||||
util.locEnd(childNode)
|
||||
options.locStart(childNode),
|
||||
options.locEnd(childNode)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
@ -702,9 +703,9 @@ function printNodeSequence(path, options, print) {
|
|||
if (i !== node.nodes.length - 1) {
|
||||
if (
|
||||
(node.nodes[i + 1].type === "css-comment" &&
|
||||
!util.hasNewline(
|
||||
!privateUtil.hasNewline(
|
||||
options.originalText,
|
||||
util.locStart(node.nodes[i + 1]),
|
||||
options.locStart(node.nodes[i + 1]),
|
||||
{ backwards: true }
|
||||
)) ||
|
||||
(node.nodes[i + 1].type === "css-atrule" &&
|
||||
|
@ -714,7 +715,13 @@ function printNodeSequence(path, options, print) {
|
|||
parts.push(" ");
|
||||
} else {
|
||||
parts.push(hardline);
|
||||
if (util.isNextLineEmpty(options.originalText, pathChild.getValue())) {
|
||||
if (
|
||||
sharedUtil.isNextLineEmpty(
|
||||
options.originalText,
|
||||
pathChild.getValue(),
|
||||
options
|
||||
)
|
||||
) {
|
||||
parts.push(hardline);
|
||||
}
|
||||
}
|
||||
|
@ -739,7 +746,9 @@ const ADJUST_NUMBERS_REGEX = RegExp(
|
|||
);
|
||||
|
||||
function adjustStrings(value, options) {
|
||||
return value.replace(STRING_REGEX, match => util.printString(match, options));
|
||||
return value.replace(STRING_REGEX, match =>
|
||||
privateUtil.printString(match, options)
|
||||
);
|
||||
}
|
||||
|
||||
function quoteAttributeValue(value, options) {
|
||||
|
@ -761,7 +770,7 @@ function adjustNumbers(value) {
|
|||
|
||||
function printNumber(rawNumber) {
|
||||
return (
|
||||
util
|
||||
privateUtil
|
||||
.printNumber(rawNumber)
|
||||
// Remove trailing `.0`.
|
||||
.replace(/\.0(?=$|e)/, "")
|
||||
|
@ -789,6 +798,6 @@ function isWideKeywords(value) {
|
|||
|
||||
module.exports = {
|
||||
print: genericPrint,
|
||||
hasPrettierIgnore: util.hasIgnoreComment,
|
||||
hasPrettierIgnore: privateUtil.hasIgnoreComment,
|
||||
massageAstNode: clean
|
||||
};
|
||||
|
|
|
@ -24,7 +24,19 @@ const parsers = {
|
|||
get parse() {
|
||||
return eval("require")("./parser-graphql");
|
||||
},
|
||||
astFormat: "graphql"
|
||||
astFormat: "graphql",
|
||||
locStart: function(node) {
|
||||
if (typeof node.start === "number") {
|
||||
return node.start;
|
||||
}
|
||||
return node.loc && node.loc.start;
|
||||
},
|
||||
locEnd: function(node) {
|
||||
if (typeof node.end === "number") {
|
||||
return node.end;
|
||||
}
|
||||
return node.loc && node.loc.end;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ const softline = docBuilders.softline;
|
|||
const group = docBuilders.group;
|
||||
const indent = docBuilders.indent;
|
||||
const ifBreak = docBuilders.ifBreak;
|
||||
|
||||
const util = require("../common/util");
|
||||
const privateUtil = require("../common/util");
|
||||
const sharedUtil = require("../common/util-shared");
|
||||
|
||||
function genericPrint(path, options, print) {
|
||||
const n = path.getValue();
|
||||
|
@ -30,7 +30,7 @@ function genericPrint(path, options, print) {
|
|||
]);
|
||||
}
|
||||
case "OperationDefinition": {
|
||||
const hasOperation = options.originalText[util.locStart(n)] !== "{";
|
||||
const hasOperation = options.originalText[options.locStart(n)] !== "{";
|
||||
const hasName = !!n.name;
|
||||
return concat([
|
||||
hasOperation ? n.operation : "",
|
||||
|
@ -591,7 +591,11 @@ function printSequence(sequencePath, options, print) {
|
|||
const printed = print(path);
|
||||
|
||||
if (
|
||||
util.isNextLineEmpty(options.originalText, path.getValue()) &&
|
||||
sharedUtil.isNextLineEmpty(
|
||||
options.originalText,
|
||||
path.getValue(),
|
||||
options
|
||||
) &&
|
||||
i < count - 1
|
||||
) {
|
||||
return concat([printed, hardline]);
|
||||
|
@ -618,7 +622,7 @@ function printComment(commentPath) {
|
|||
|
||||
module.exports = {
|
||||
print: genericPrint,
|
||||
hasPrettierIgnore: util.hasIgnoreComment,
|
||||
hasPrettierIgnore: privateUtil.hasIgnoreComment,
|
||||
printComment,
|
||||
canAttachComment
|
||||
};
|
||||
|
|
|
@ -22,7 +22,13 @@ const parsers = {
|
|||
get parse() {
|
||||
return eval("require")("./parser-glimmer");
|
||||
},
|
||||
astFormat: "glimmer"
|
||||
astFormat: "glimmer",
|
||||
locEnd: function(node) {
|
||||
return node.loc && node.loc.end;
|
||||
},
|
||||
locStart: function(node) {
|
||||
return node.loc && node.loc.start;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
const util = require("../common/util");
|
||||
const privateUtil = require("../common/util");
|
||||
const doc = require("../doc");
|
||||
const docUtils = doc.utils;
|
||||
const docBuilders = doc.builders;
|
||||
|
@ -66,7 +66,7 @@ function embed(path, print, textToDoc, options) {
|
|||
return concat([
|
||||
node.key,
|
||||
'="',
|
||||
util.hasNewlineInRange(node.value, 0, node.value.length)
|
||||
privateUtil.hasNewlineInRange(node.value, 0, node.value.length)
|
||||
? doc
|
||||
: docUtils.removeLines(doc),
|
||||
'"'
|
||||
|
@ -87,7 +87,10 @@ function parseJavaScriptExpression(text, parsers) {
|
|||
}
|
||||
|
||||
function getText(options, node) {
|
||||
return options.originalText.slice(util.locStart(node), util.locEnd(node));
|
||||
return options.originalText.slice(
|
||||
options.locStart(node),
|
||||
options.locEnd(node)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = embed;
|
||||
|
|
|
@ -27,7 +27,13 @@ const parsers = {
|
|||
get parse() {
|
||||
return eval("require")("./parser-parse5");
|
||||
},
|
||||
astFormat: "htmlparser2"
|
||||
astFormat: "htmlparser2",
|
||||
locEnd: function(node) {
|
||||
return node.__location && node.__location.endOffset;
|
||||
},
|
||||
locStart: function(node) {
|
||||
return node.__location && node.__location.startOffset;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
"use strict";
|
||||
|
||||
const embed = require("./embed");
|
||||
const util = require("../common/util");
|
||||
const privateUtil = require("../common/util");
|
||||
const docBuilders = require("../doc").builders;
|
||||
const concat = docBuilders.concat;
|
||||
const join = docBuilders.join;
|
||||
|
@ -55,10 +55,10 @@ function genericPrint(path, options, print) {
|
|||
const selfClose = voidTags[n.name] ? ">" : " />";
|
||||
const children = printChildren(path, print);
|
||||
|
||||
const hasNewline = util.hasNewlineInRange(
|
||||
const hasNewline = privateUtil.hasNewlineInRange(
|
||||
options.originalText,
|
||||
util.locStart(n),
|
||||
util.locEnd(n)
|
||||
options.locStart(n),
|
||||
options.locEnd(n)
|
||||
);
|
||||
|
||||
return group(
|
||||
|
@ -117,5 +117,5 @@ function printChildren(path, print) {
|
|||
module.exports = {
|
||||
print: genericPrint,
|
||||
embed,
|
||||
hasPrettierIgnore: util.hasIgnoreComment
|
||||
hasPrettierIgnore: privateUtil.hasIgnoreComment
|
||||
};
|
||||
|
|
|
@ -2,10 +2,66 @@
|
|||
|
||||
const printer = require("./printer-estree");
|
||||
const options = require("./options");
|
||||
const privateUtil = require("../common/util");
|
||||
|
||||
// Based on:
|
||||
// https://github.com/github/linguist/blob/master/lib/linguist/languages.yml
|
||||
|
||||
const locStart = function(node) {
|
||||
// Handle nodes with decorators. They should start at the first decorator
|
||||
if (
|
||||
node.declaration &&
|
||||
node.declaration.decorators &&
|
||||
node.declaration.decorators.length > 0
|
||||
) {
|
||||
return locStart(node.declaration.decorators[0]);
|
||||
}
|
||||
if (node.decorators && node.decorators.length > 0) {
|
||||
return locStart(node.decorators[0]);
|
||||
}
|
||||
|
||||
if (node.__location) {
|
||||
return node.__location.startOffset;
|
||||
}
|
||||
if (node.range) {
|
||||
return node.range[0];
|
||||
}
|
||||
if (typeof node.start === "number") {
|
||||
return node.start;
|
||||
}
|
||||
if (node.loc) {
|
||||
return node.loc.start;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const locEnd = function(node) {
|
||||
const endNode = node.nodes && privateUtil.getLast(node.nodes);
|
||||
if (endNode && node.source && !node.source.end) {
|
||||
node = endNode;
|
||||
}
|
||||
|
||||
let loc;
|
||||
if (node.range) {
|
||||
loc = node.range[1];
|
||||
} else if (typeof node.end === "number") {
|
||||
loc = node.end;
|
||||
}
|
||||
|
||||
if (node.__location) {
|
||||
return node.__location.endOffset;
|
||||
}
|
||||
if (node.typeAnnotation) {
|
||||
return Math.max(loc, locEnd(node.typeAnnotation));
|
||||
}
|
||||
|
||||
if (node.loc && !loc) {
|
||||
return node.loc.end;
|
||||
}
|
||||
|
||||
return loc;
|
||||
};
|
||||
|
||||
const languages = [
|
||||
{
|
||||
name: "JavaScript",
|
||||
|
@ -104,14 +160,18 @@ const typescript = {
|
|||
get parse() {
|
||||
return eval("require")("./parser-typescript");
|
||||
},
|
||||
astFormat: "estree"
|
||||
astFormat: "estree",
|
||||
locStart,
|
||||
locEnd
|
||||
};
|
||||
|
||||
const babylon = {
|
||||
get parse() {
|
||||
return eval("require")("./parser-babylon");
|
||||
},
|
||||
astFormat: "estree"
|
||||
astFormat: "estree",
|
||||
locStart,
|
||||
locEnd
|
||||
};
|
||||
|
||||
const parsers = {
|
||||
|
@ -121,7 +181,9 @@ const parsers = {
|
|||
get parse() {
|
||||
return eval("require")("./parser-flow");
|
||||
},
|
||||
astFormat: "estree"
|
||||
astFormat: "estree",
|
||||
locStart,
|
||||
locEnd
|
||||
},
|
||||
"typescript-eslint": typescript,
|
||||
// TODO: Delete this in 2.0
|
||||
|
@ -136,5 +198,7 @@ module.exports = {
|
|||
languages,
|
||||
options,
|
||||
parsers,
|
||||
printers
|
||||
printers,
|
||||
locStart,
|
||||
locEnd
|
||||
};
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
const assert = require("assert");
|
||||
// TODO(azz): anything that imports from main shouldn't be in a `language-*` dir.
|
||||
const comments = require("../main/comments");
|
||||
const util = require("../common/util");
|
||||
const privateUtil = require("../common/util");
|
||||
const sharedUtil = require("../common/util-shared");
|
||||
const isIdentifierName = require("esutils").keyword.isIdentifierNameES6;
|
||||
const embed = require("./embed");
|
||||
const clean = require("./clean");
|
||||
|
@ -68,7 +69,7 @@ function genericPrint(path, options, printPath, args) {
|
|||
node.decorators.length > 0 &&
|
||||
// If the parent node is an export declaration, it will be
|
||||
// responsible for printing node.decorators.
|
||||
!util.getParentExportDeclaration(path)
|
||||
!privateUtil.getParentExportDeclaration(path)
|
||||
) {
|
||||
let separator = hardline;
|
||||
path.each(decoratorPath => {
|
||||
|
@ -99,7 +100,7 @@ function genericPrint(path, options, printPath, args) {
|
|||
decorators.push(prefix, printPath(decoratorPath), separator);
|
||||
}, "decorators");
|
||||
} else if (
|
||||
util.isExportDeclaration(node) &&
|
||||
privateUtil.isExportDeclaration(node) &&
|
||||
node.declaration &&
|
||||
node.declaration.decorators
|
||||
) {
|
||||
|
@ -138,7 +139,7 @@ function genericPrint(path, options, printPath, args) {
|
|||
}
|
||||
|
||||
function hasPrettierIgnore(path) {
|
||||
return util.hasIgnoreComment(path) || hasJsxIgnoreComment(path);
|
||||
return privateUtil.hasIgnoreComment(path) || hasJsxIgnoreComment(path);
|
||||
}
|
||||
|
||||
function hasJsxIgnoreComment(path) {
|
||||
|
@ -193,7 +194,11 @@ function printPathNoParens(path, options, print, args) {
|
|||
path.each(childPath => {
|
||||
parts.push(print(childPath), semi, hardline);
|
||||
if (
|
||||
util.isNextLineEmpty(options.originalText, childPath.getValue())
|
||||
sharedUtil.isNextLineEmpty(
|
||||
options.originalText,
|
||||
childPath.getValue(),
|
||||
options
|
||||
)
|
||||
) {
|
||||
parts.push(hardline);
|
||||
}
|
||||
|
@ -306,7 +311,8 @@ function printPathNoParens(path, options, print, args) {
|
|||
parent.type === "Property";
|
||||
|
||||
const samePrecedenceSubExpression =
|
||||
isBinaryish(n.left) && util.shouldFlatten(n.operator, n.left.operator);
|
||||
isBinaryish(n.left) &&
|
||||
privateUtil.shouldFlatten(n.operator, n.left.operator);
|
||||
|
||||
if (
|
||||
shouldNotIndent ||
|
||||
|
@ -452,9 +458,10 @@ function printPathNoParens(path, options, print, args) {
|
|||
options,
|
||||
/* sameIndent */ true,
|
||||
comment => {
|
||||
const nextCharacter = util.getNextNonSpaceNonCommentCharacterIndex(
|
||||
const nextCharacter = sharedUtil.getNextNonSpaceNonCommentCharacterIndex(
|
||||
options.originalText,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
);
|
||||
return options.originalText.substr(nextCharacter, 2) === "=>";
|
||||
}
|
||||
|
@ -470,12 +477,12 @@ function printPathNoParens(path, options, print, args) {
|
|||
// We want to always keep these types of nodes on the same line
|
||||
// as the arrow.
|
||||
if (
|
||||
!hasLeadingOwnLineComment(options.originalText, n.body) &&
|
||||
!hasLeadingOwnLineComment(options.originalText, n.body, options) &&
|
||||
(n.body.type === "ArrayExpression" ||
|
||||
n.body.type === "ObjectExpression" ||
|
||||
n.body.type === "BlockStatement" ||
|
||||
isJSXNode(n.body) ||
|
||||
isTemplateOnItsOwnLine(n.body, options.originalText) ||
|
||||
isTemplateOnItsOwnLine(n.body, options.originalText, options) ||
|
||||
n.body.type === "ArrowFunctionExpression")
|
||||
) {
|
||||
return group(concat([concat(parts), " ", body]));
|
||||
|
@ -511,7 +518,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
// a <= a ? a : a
|
||||
const shouldAddParens =
|
||||
n.body.type === "ConditionalExpression" &&
|
||||
!util.startsWithNoLookaheadToken(
|
||||
!privateUtil.startsWithNoLookaheadToken(
|
||||
n.body,
|
||||
/* forbidFunctionAndClass */ false
|
||||
);
|
||||
|
@ -689,7 +696,10 @@ function printPathNoParens(path, options, print, args) {
|
|||
(n.importKind && n.importKind === "type") ||
|
||||
// import {} from 'x'
|
||||
/{\s*}/.test(
|
||||
options.originalText.slice(util.locStart(n), util.locStart(n.source))
|
||||
options.originalText.slice(
|
||||
options.locStart(n),
|
||||
options.locStart(n.source)
|
||||
)
|
||||
)
|
||||
) {
|
||||
parts.push("{} from ");
|
||||
|
@ -736,7 +746,11 @@ function printPathNoParens(path, options, print, args) {
|
|||
path.each(childPath => {
|
||||
parts.push(indent(concat([hardline, print(childPath), semi])));
|
||||
if (
|
||||
util.isNextLineEmpty(options.originalText, childPath.getValue())
|
||||
sharedUtil.isNextLineEmpty(
|
||||
options.originalText,
|
||||
childPath.getValue(),
|
||||
options
|
||||
)
|
||||
) {
|
||||
parts.push(hardline);
|
||||
}
|
||||
|
@ -810,7 +824,11 @@ function printPathNoParens(path, options, print, args) {
|
|||
n.callee.type === "Import" ||
|
||||
// Template literals as single arguments
|
||||
(n.arguments.length === 1 &&
|
||||
isTemplateOnItsOwnLine(n.arguments[0], options.originalText)) ||
|
||||
isTemplateOnItsOwnLine(
|
||||
n.arguments[0],
|
||||
options.originalText,
|
||||
options
|
||||
)) ||
|
||||
// Keep test declarations on a single line
|
||||
// e.g. `it('long name', () => {`
|
||||
(!isNew && isTestCall(n))
|
||||
|
@ -879,10 +897,10 @@ function printPathNoParens(path, options, print, args) {
|
|||
const shouldBreak =
|
||||
n.type === "TSInterfaceBody" ||
|
||||
(n.type !== "ObjectPattern" &&
|
||||
util.hasNewlineInRange(
|
||||
privateUtil.hasNewlineInRange(
|
||||
options.originalText,
|
||||
util.locStart(n),
|
||||
util.locEnd(n)
|
||||
options.locStart(n),
|
||||
options.locEnd(n)
|
||||
));
|
||||
const parent = path.getParentNode(0);
|
||||
const isFlowInterfaceLikeBody =
|
||||
|
@ -926,7 +944,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
propsAndLoc.push({
|
||||
node: node,
|
||||
printed: print(childPath),
|
||||
loc: util.locStart(node)
|
||||
loc: options.locStart(node)
|
||||
});
|
||||
}, field);
|
||||
});
|
||||
|
@ -937,24 +955,26 @@ function printPathNoParens(path, options, print, args) {
|
|||
separatorParts = [separator, line];
|
||||
if (
|
||||
prop.node.type === "TSPropertySignature" &&
|
||||
util.hasNodeIgnoreComment(prop.node)
|
||||
privateUtil.hasNodeIgnoreComment(prop.node)
|
||||
) {
|
||||
separatorParts.shift();
|
||||
}
|
||||
if (util.isNextLineEmpty(options.originalText, prop.node)) {
|
||||
if (
|
||||
sharedUtil.isNextLineEmpty(options.originalText, prop.node, options)
|
||||
) {
|
||||
separatorParts.push(hardline);
|
||||
}
|
||||
return result;
|
||||
});
|
||||
|
||||
const lastElem = util.getLast(n[propertiesField]);
|
||||
const lastElem = privateUtil.getLast(n[propertiesField]);
|
||||
|
||||
const canHaveTrailingSeparator = !(
|
||||
lastElem &&
|
||||
(lastElem.type === "RestProperty" ||
|
||||
lastElem.type === "RestElement" ||
|
||||
lastElem.type === "ExperimentalRestProperty" ||
|
||||
util.hasNodeIgnoreComment(lastElem))
|
||||
privateUtil.hasNodeIgnoreComment(lastElem))
|
||||
);
|
||||
|
||||
let content;
|
||||
|
@ -1068,7 +1088,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
const lastElem = util.getLast(n.elements);
|
||||
const lastElem = privateUtil.getLast(n.elements);
|
||||
const canHaveTrailingComma = !(
|
||||
lastElem && lastElem.type === "RestElement"
|
||||
);
|
||||
|
@ -1081,7 +1101,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
// [1,].length === 1
|
||||
// [1,,].length === 2
|
||||
//
|
||||
// Note that util.getLast returns null if the array is empty, but
|
||||
// Note that privateUtil.getLast returns null if the array is empty, but
|
||||
// we already check for an empty array just above so we are safe
|
||||
const needsForcedTrailingComma =
|
||||
canHaveTrailingComma && lastElem === null;
|
||||
|
@ -1154,7 +1174,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
case "RegExpLiteral": // Babel 6 Literal split
|
||||
return printRegex(n);
|
||||
case "NumericLiteral": // Babel 6 Literal split
|
||||
return util.printNumber(n.extra.raw);
|
||||
return privateUtil.printNumber(n.extra.raw);
|
||||
case "BooleanLiteral": // Babel 6 Literal split
|
||||
case "StringLiteral": // Babel 6 Literal split
|
||||
case "Literal": {
|
||||
|
@ -1162,7 +1182,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
return printRegex(n.regex);
|
||||
}
|
||||
if (typeof n.value === "number") {
|
||||
return util.printNumber(n.raw);
|
||||
return privateUtil.printNumber(n.raw);
|
||||
}
|
||||
if (typeof n.value !== "string") {
|
||||
return "" + n.value;
|
||||
|
@ -1588,7 +1608,11 @@ function printPathNoParens(path, options, print, args) {
|
|||
return concat([
|
||||
casePath.call(print),
|
||||
n.cases.indexOf(caseNode) !== n.cases.length - 1 &&
|
||||
util.isNextLineEmpty(options.originalText, caseNode)
|
||||
sharedUtil.isNextLineEmpty(
|
||||
options.originalText,
|
||||
caseNode,
|
||||
options
|
||||
)
|
||||
? hardline
|
||||
: ""
|
||||
]);
|
||||
|
@ -1775,7 +1799,8 @@ function printPathNoParens(path, options, print, args) {
|
|||
}
|
||||
|
||||
const lastAttrHasTrailingComments =
|
||||
n.attributes.length && hasTrailingComment(util.getLast(n.attributes));
|
||||
n.attributes.length &&
|
||||
hasTrailingComment(privateUtil.getLast(n.attributes));
|
||||
|
||||
const bracketSameLine =
|
||||
options.jsxBracketSameLine &&
|
||||
|
@ -1813,7 +1838,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
case "TSJsxClosingFragment": {
|
||||
const hasComment = n.comments && n.comments.length;
|
||||
const hasOwnLineComment =
|
||||
hasComment && !n.comments.every(util.isBlockComment);
|
||||
hasComment && !n.comments.every(privateUtil.isBlockComment);
|
||||
const isOpeningFragment =
|
||||
n.type === "JSXOpeningFragment" || n.type === "TSJsxOpeningFragment";
|
||||
return concat([
|
||||
|
@ -1835,7 +1860,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
throw new Error("JSXTest should be handled by JSXElement");
|
||||
case "JSXEmptyExpression": {
|
||||
const requiresHardline =
|
||||
n.comments && !n.comments.every(util.isBlockComment);
|
||||
n.comments && !n.comments.every(privateUtil.isBlockComment);
|
||||
|
||||
return concat([
|
||||
comments.printDanglingComments(
|
||||
|
@ -1948,7 +1973,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
// expression inside at the beginning of ${ instead of the beginning
|
||||
// of the `.
|
||||
const tabWidth = options.tabWidth;
|
||||
const indentSize = util.getIndentSize(
|
||||
const indentSize = privateUtil.getIndentSize(
|
||||
childPath.getValue().value.raw,
|
||||
tabWidth
|
||||
);
|
||||
|
@ -2118,7 +2143,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
(parent.type === "ObjectTypeProperty" &&
|
||||
!getFlowVariance(parent) &&
|
||||
!parent.optional &&
|
||||
util.locStart(parent) === util.locStart(n)) ||
|
||||
options.locStart(parent) === options.locStart(n)) ||
|
||||
parent.type === "ObjectTypeCallProperty" ||
|
||||
(parentParentParent && parentParentParent.type === "DeclareFunction")
|
||||
);
|
||||
|
@ -2138,7 +2163,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
parent.type === "TSTypeAnnotation") &&
|
||||
parentParent.type === "ArrowFunctionExpression";
|
||||
|
||||
if (isObjectTypePropertyAFunction(parent)) {
|
||||
if (isObjectTypePropertyAFunction(parent, options)) {
|
||||
isArrowFunctionTypeAnnotation = true;
|
||||
needsColon = true;
|
||||
}
|
||||
|
@ -2269,7 +2294,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
!(
|
||||
(parent.type === "TypeAlias" ||
|
||||
parent.type === "VariableDeclarator") &&
|
||||
hasLeadingOwnLineComment(options.originalText, n)
|
||||
hasLeadingOwnLineComment(options.originalText, n, options)
|
||||
);
|
||||
|
||||
// {
|
||||
|
@ -2359,7 +2384,7 @@ function printPathNoParens(path, options, print, args) {
|
|||
variance || "",
|
||||
printPropertyKey(path, options, print),
|
||||
printOptionalToken(path),
|
||||
isFunctionNotation(n) ? "" : ": ",
|
||||
isFunctionNotation(n, options) ? "" : ": ",
|
||||
path.call(print, "value")
|
||||
]);
|
||||
}
|
||||
|
@ -2375,9 +2400,9 @@ function printPathNoParens(path, options, print, args) {
|
|||
assert.strictEqual(typeof n.value, "number");
|
||||
|
||||
if (n.extra != null) {
|
||||
return util.printNumber(n.extra.raw);
|
||||
return privateUtil.printNumber(n.extra.raw);
|
||||
}
|
||||
return util.printNumber(n.raw);
|
||||
return privateUtil.printNumber(n.raw);
|
||||
|
||||
case "StringTypeAnnotation":
|
||||
return "string";
|
||||
|
@ -2787,7 +2812,10 @@ function printPathNoParens(path, options, print, args) {
|
|||
n.id.type === "Identifier" &&
|
||||
n.id.name === "global" &&
|
||||
!/namespace|module/.test(
|
||||
options.originalText.slice(util.locStart(n), util.locStart(n.id))
|
||||
options.originalText.slice(
|
||||
options.locStart(n),
|
||||
options.locStart(n.id)
|
||||
)
|
||||
);
|
||||
|
||||
if (!isGlobalDeclaration) {
|
||||
|
@ -2890,7 +2918,10 @@ function printStatementSequence(path, options, print) {
|
|||
}
|
||||
}
|
||||
|
||||
if (util.isNextLineEmpty(text, stmt) && !isLastStatement(stmtPath)) {
|
||||
if (
|
||||
sharedUtil.isNextLineEmpty(text, stmt, options) &&
|
||||
!isLastStatement(stmtPath)
|
||||
) {
|
||||
parts.push(hardline);
|
||||
}
|
||||
|
||||
|
@ -2996,8 +3027,8 @@ function couldGroupArg(arg) {
|
|||
}
|
||||
|
||||
function shouldGroupLastArg(args) {
|
||||
const lastArg = util.getLast(args);
|
||||
const penultimateArg = util.getPenultimate(args);
|
||||
const lastArg = privateUtil.getLast(args);
|
||||
const penultimateArg = privateUtil.getPenultimate(args);
|
||||
return (
|
||||
!hasLeadingComment(lastArg) &&
|
||||
!hasTrailingComment(lastArg) &&
|
||||
|
@ -3044,7 +3075,7 @@ function printArgumentsList(path, options, print) {
|
|||
|
||||
if (index === lastArgIndex) {
|
||||
// do nothing
|
||||
} else if (util.isNextLineEmpty(options.originalText, arg)) {
|
||||
} else if (sharedUtil.isNextLineEmpty(options.originalText, arg, options)) {
|
||||
if (index === 0) {
|
||||
hasEmptyLineFollowingFirstArg = true;
|
||||
}
|
||||
|
@ -3119,7 +3150,7 @@ function printArgumentsList(path, options, print) {
|
|||
: concat([
|
||||
"(",
|
||||
concat(printedArguments.slice(0, -1)),
|
||||
group(util.getLast(printedExpanded), {
|
||||
group(privateUtil.getLast(printedExpanded), {
|
||||
shouldBreak: true
|
||||
}),
|
||||
")"
|
||||
|
@ -3162,7 +3193,9 @@ function printTypeAnnotation(path, options, print) {
|
|||
const isFunctionDeclarationIdentifier =
|
||||
parentNode.type === "DeclareFunction" && parentNode.id === node;
|
||||
|
||||
if (isFlowAnnotationComment(options.originalText, node.typeAnnotation)) {
|
||||
if (
|
||||
isFlowAnnotationComment(options.originalText, node.typeAnnotation, options)
|
||||
) {
|
||||
return concat([" /*: ", path.call(print, "typeAnnotation"), " */"]);
|
||||
}
|
||||
|
||||
|
@ -3206,16 +3239,17 @@ function printFunctionParams(path, print, options, expandArg, printTypeParams) {
|
|||
options,
|
||||
/* sameIndent */ true,
|
||||
comment =>
|
||||
util.getNextNonSpaceNonCommentCharacter(
|
||||
privateUtil.getNextNonSpaceNonCommentCharacter(
|
||||
options.originalText,
|
||||
comment
|
||||
comment,
|
||||
options.locEnd
|
||||
) === ")"
|
||||
),
|
||||
")"
|
||||
]);
|
||||
}
|
||||
|
||||
const lastParam = util.getLast(fun[paramsField]);
|
||||
const lastParam = privateUtil.getLast(fun[paramsField]);
|
||||
|
||||
// If the parent is a call with the first/last argument expansion and this is the
|
||||
// params of the first/last argument, we dont want the arguments to break and instead
|
||||
|
@ -3274,8 +3308,8 @@ function printFunctionParams(path, print, options, expandArg, printTypeParams) {
|
|||
];
|
||||
|
||||
const isFlowShorthandWithOneArg =
|
||||
(isObjectTypePropertyAFunction(parent) ||
|
||||
isTypeAnnotationAFunction(parent) ||
|
||||
(isObjectTypePropertyAFunction(parent, options) ||
|
||||
isTypeAnnotationAFunction(parent, options) ||
|
||||
parent.type === "TypeAlias" ||
|
||||
parent.type === "UnionTypeAnnotation" ||
|
||||
parent.type === "TSUnionType" ||
|
||||
|
@ -3424,7 +3458,7 @@ function printReturnType(path, print, options) {
|
|||
|
||||
if (
|
||||
n.returnType &&
|
||||
isFlowAnnotationComment(options.originalText, n.returnType)
|
||||
isFlowAnnotationComment(options.originalText, n.returnType, options)
|
||||
) {
|
||||
return concat([" /*: ", returnType, " */"]);
|
||||
}
|
||||
|
@ -3530,7 +3564,7 @@ function printExportDeclaration(path, options, print) {
|
|||
}
|
||||
|
||||
function printFlowDeclaration(path, parts) {
|
||||
const parentExportDecl = util.getParentExportDeclaration(path);
|
||||
const parentExportDecl = privateUtil.getParentExportDeclaration(path);
|
||||
|
||||
if (parentExportDecl) {
|
||||
assert.strictEqual(parentExportDecl.type, "DeclareExportDeclaration");
|
||||
|
@ -3714,7 +3748,7 @@ function printClass(path, options, print) {
|
|||
if (
|
||||
n.body &&
|
||||
n.body.comments &&
|
||||
hasLeadingOwnLineComment(options.originalText, n.body)
|
||||
hasLeadingOwnLineComment(options.originalText, n.body, options)
|
||||
) {
|
||||
parts.push(hardline);
|
||||
} else {
|
||||
|
@ -3786,19 +3820,24 @@ function printMemberChain(path, options, print) {
|
|||
// the first group whether it is in parentheses or not
|
||||
function shouldInsertEmptyLineAfter(node) {
|
||||
const originalText = options.originalText;
|
||||
const nextCharIndex = util.getNextNonSpaceNonCommentCharacterIndex(
|
||||
const nextCharIndex = sharedUtil.getNextNonSpaceNonCommentCharacterIndex(
|
||||
originalText,
|
||||
node
|
||||
node,
|
||||
options
|
||||
);
|
||||
const nextChar = originalText.charAt(nextCharIndex);
|
||||
|
||||
// if it is cut off by a parenthesis, we only account for one typed empty
|
||||
// line after that parenthesis
|
||||
if (nextChar == ")") {
|
||||
return util.isNextLineEmptyAfterIndex(originalText, nextCharIndex + 1);
|
||||
return sharedUtil.isNextLineEmptyAfterIndex(
|
||||
originalText,
|
||||
nextCharIndex + 1,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
return util.isNextLineEmpty(originalText, node);
|
||||
return sharedUtil.isNextLineEmpty(originalText, node, options);
|
||||
}
|
||||
|
||||
function rec(path) {
|
||||
|
@ -4015,7 +4054,7 @@ function printMemberChain(path, options, print) {
|
|||
|
||||
// Find out the last node in the first group and check if it has an
|
||||
// empty line after
|
||||
const lastNodeBeforeIndent = util.getLast(
|
||||
const lastNodeBeforeIndent = privateUtil.getLast(
|
||||
shouldMerge ? groups.slice(1, 2)[0] : groups[0]
|
||||
).node;
|
||||
const shouldHaveEmptyLineBeforeIndent =
|
||||
|
@ -4240,7 +4279,7 @@ function printJSXChildren(path, options, print, jsxWhitespace) {
|
|||
|
||||
let endWhitespace;
|
||||
// Ends with whitespace
|
||||
if (util.getLast(words) === "") {
|
||||
if (privateUtil.getLast(words) === "") {
|
||||
words.pop();
|
||||
endWhitespace = words.pop();
|
||||
}
|
||||
|
@ -4428,7 +4467,8 @@ function printJSXElement(path, options, print) {
|
|||
// Trim trailing lines (or empty strings)
|
||||
while (
|
||||
children.length &&
|
||||
(isLineNext(util.getLast(children)) || isEmpty(util.getLast(children)))
|
||||
(isLineNext(privateUtil.getLast(children)) ||
|
||||
isEmpty(privateUtil.getLast(children)))
|
||||
) {
|
||||
children.pop();
|
||||
}
|
||||
|
@ -4600,7 +4640,7 @@ function printBinaryishExpressions(
|
|||
// precedence level and should be treated as a separate group, so
|
||||
// print them normally. (This doesn't hold for the `**` operator,
|
||||
// which is unique in that it is right-associative.)
|
||||
if (util.shouldFlatten(node.operator, node.left.operator)) {
|
||||
if (privateUtil.shouldFlatten(node.operator, node.left.operator)) {
|
||||
// Flatten them out by recursively calling this function.
|
||||
parts = parts.concat(
|
||||
path.call(
|
||||
|
@ -4657,7 +4697,7 @@ function printBinaryishExpressions(
|
|||
}
|
||||
|
||||
function printAssignmentRight(rightNode, printedRight, canBreak, options) {
|
||||
if (hasLeadingOwnLineComment(options.originalText, rightNode)) {
|
||||
if (hasLeadingOwnLineComment(options.originalText, rightNode, options)) {
|
||||
return indent(concat([hardline, printedRight]));
|
||||
}
|
||||
|
||||
|
@ -4716,7 +4756,7 @@ function nodeStr(node, options, isFlowOrTypeScriptDirectiveLiteral) {
|
|||
const raw = rawText(node);
|
||||
const isDirectiveLiteral =
|
||||
isFlowOrTypeScriptDirectiveLiteral || node.type === "DirectiveLiteral";
|
||||
return util.printString(raw, options, isDirectiveLiteral);
|
||||
return privateUtil.printString(raw, options, isDirectiveLiteral);
|
||||
}
|
||||
|
||||
function printRegex(node) {
|
||||
|
@ -4747,15 +4787,16 @@ function hasTrailingComment(node) {
|
|||
return node.comments && node.comments.some(comment => comment.trailing);
|
||||
}
|
||||
|
||||
function hasLeadingOwnLineComment(text, node) {
|
||||
function hasLeadingOwnLineComment(text, node, options) {
|
||||
if (isJSXNode(node)) {
|
||||
return util.hasNodeIgnoreComment(node);
|
||||
return privateUtil.hasNodeIgnoreComment(node);
|
||||
}
|
||||
|
||||
const res =
|
||||
node.comments &&
|
||||
node.comments.some(
|
||||
comment => comment.leading && util.hasNewline(text, util.locEnd(comment))
|
||||
comment =>
|
||||
comment.leading && privateUtil.hasNewline(text, options.locEnd(comment))
|
||||
);
|
||||
return res;
|
||||
}
|
||||
|
@ -4775,9 +4816,9 @@ function hasNakedLeftSide(node) {
|
|||
);
|
||||
}
|
||||
|
||||
function isFlowAnnotationComment(text, typeAnnotation) {
|
||||
const start = util.locStart(typeAnnotation);
|
||||
const end = util.skipWhitespace(text, util.locEnd(typeAnnotation));
|
||||
function isFlowAnnotationComment(text, typeAnnotation, options) {
|
||||
const start = options.locStart(typeAnnotation);
|
||||
const end = privateUtil.skipWhitespace(text, options.locEnd(typeAnnotation));
|
||||
return text.substr(start, 2) === "/*" && text.substr(end, 2) === "*/";
|
||||
}
|
||||
|
||||
|
@ -4940,7 +4981,7 @@ function classChildNeedsASIProtection(node) {
|
|||
// (the leftmost leaf node) and, if it (or its parents) has any
|
||||
// leadingComments, returns true (so it can be wrapped in parens).
|
||||
function returnArgumentHasLeadingComment(options, argument) {
|
||||
if (hasLeadingOwnLineComment(options.originalText, argument)) {
|
||||
if (hasLeadingOwnLineComment(options.originalText, argument, options)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -4950,7 +4991,7 @@ function returnArgumentHasLeadingComment(options, argument) {
|
|||
while ((newLeftMost = getLeftSide(leftMost))) {
|
||||
leftMost = newLeftMost;
|
||||
|
||||
if (hasLeadingOwnLineComment(options.originalText, leftMost)) {
|
||||
if (hasLeadingOwnLineComment(options.originalText, leftMost, options)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -4972,38 +5013,38 @@ function isMemberExpressionChain(node) {
|
|||
// Hack to differentiate between the following two which have the same ast
|
||||
// type T = { method: () => void };
|
||||
// type T = { method(): void };
|
||||
function isObjectTypePropertyAFunction(node) {
|
||||
function isObjectTypePropertyAFunction(node, options) {
|
||||
return (
|
||||
node.type === "ObjectTypeProperty" &&
|
||||
node.value.type === "FunctionTypeAnnotation" &&
|
||||
!node.static &&
|
||||
!isFunctionNotation(node)
|
||||
!isFunctionNotation(node, options)
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: This is a bad hack and we need a better way to distinguish between
|
||||
// arrow functions and otherwise
|
||||
function isFunctionNotation(node) {
|
||||
return isGetterOrSetter(node) || sameLocStart(node, node.value);
|
||||
function isFunctionNotation(node, options) {
|
||||
return isGetterOrSetter(node) || sameLocStart(node, node.value, options);
|
||||
}
|
||||
|
||||
function isGetterOrSetter(node) {
|
||||
return node.kind === "get" || node.kind === "set";
|
||||
}
|
||||
|
||||
function sameLocStart(nodeA, nodeB) {
|
||||
return util.locStart(nodeA) === util.locStart(nodeB);
|
||||
function sameLocStart(nodeA, nodeB, options) {
|
||||
return options.locStart(nodeA) === options.locStart(nodeB);
|
||||
}
|
||||
|
||||
// Hack to differentiate between the following two which have the same ast
|
||||
// declare function f(a): void;
|
||||
// var f: (a) => void;
|
||||
function isTypeAnnotationAFunction(node) {
|
||||
function isTypeAnnotationAFunction(node, options) {
|
||||
return (
|
||||
(node.type === "TypeAnnotation" || node.type === "TSTypeAnnotation") &&
|
||||
node.typeAnnotation.type === "FunctionTypeAnnotation" &&
|
||||
!node.static &&
|
||||
!sameLocStart(node, node.typeAnnotation)
|
||||
!sameLocStart(node, node.typeAnnotation, options)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5013,7 +5054,7 @@ function isNodeStartingWithDeclare(node, options) {
|
|||
}
|
||||
return (
|
||||
options.originalText
|
||||
.slice(0, util.locStart(node))
|
||||
.slice(0, options.locStart(node))
|
||||
.match(/declare[ \t]*$/) ||
|
||||
options.originalText
|
||||
.slice(node.range[0], node.range[1])
|
||||
|
@ -5083,12 +5124,12 @@ function templateLiteralHasNewLines(template) {
|
|||
return template.quasis.some(quasi => quasi.value.raw.includes("\n"));
|
||||
}
|
||||
|
||||
function isTemplateOnItsOwnLine(n, text) {
|
||||
function isTemplateOnItsOwnLine(n, text, options) {
|
||||
return (
|
||||
((n.type === "TemplateLiteral" && templateLiteralHasNewLines(n)) ||
|
||||
(n.type === "TaggedTemplateExpression" &&
|
||||
templateLiteralHasNewLines(n.quasi))) &&
|
||||
!util.hasNewline(text, util.locStart(n), { backwards: true })
|
||||
!privateUtil.hasNewline(text, options.locStart(n), { backwards: true })
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5103,7 +5144,11 @@ function printArrayItems(path, options, printPath, print) {
|
|||
separatorParts = [",", line];
|
||||
if (
|
||||
childPath.getValue() &&
|
||||
util.isNextLineEmpty(options.originalText, childPath.getValue())
|
||||
sharedUtil.isNextLineEmpty(
|
||||
options.originalText,
|
||||
childPath.getValue(),
|
||||
options
|
||||
)
|
||||
) {
|
||||
separatorParts.push(softline);
|
||||
}
|
||||
|
@ -5204,7 +5249,7 @@ function willPrintOwnComments(path) {
|
|||
((parent.type === "ClassDeclaration" ||
|
||||
parent.type === "ClassExpression") &&
|
||||
parent.superClass === node)))) &&
|
||||
!util.hasIgnoreComment(path)
|
||||
!privateUtil.hasIgnoreComment(path)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -5233,14 +5278,16 @@ function printComment(commentPath, options) {
|
|||
}
|
||||
|
||||
const isInsideFlowComment =
|
||||
options.originalText.substr(util.locEnd(comment) - 3, 3) === "*-/";
|
||||
options.originalText.substr(options.locEnd(comment) - 3, 3) === "*-/";
|
||||
|
||||
return "/*" + comment.value + (isInsideFlowComment ? "*-/" : "*/");
|
||||
}
|
||||
case "CommentLine":
|
||||
case "Line":
|
||||
// Print shebangs with the proper comment characters
|
||||
if (options.originalText.slice(util.locStart(comment)).startsWith("#!")) {
|
||||
if (
|
||||
options.originalText.slice(options.locStart(comment)).startsWith("#!")
|
||||
) {
|
||||
return "#!" + comment.value.trimRight();
|
||||
}
|
||||
return "//" + comment.value.trimRight();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
const util = require("../common/util");
|
||||
const privateUtil = require("../common/util");
|
||||
const embed = require("./embed");
|
||||
const doc = require("../doc");
|
||||
const docBuilders = doc.builders;
|
||||
|
@ -46,7 +46,7 @@ function genericPrint(path, options, print) {
|
|||
|
||||
if (shouldRemainTheSameContent(path)) {
|
||||
return concat(
|
||||
util
|
||||
privateUtil
|
||||
.splitText(
|
||||
options.originalText.slice(
|
||||
node.position.start.offset,
|
||||
|
@ -80,8 +80,8 @@ function genericPrint(path, options, print) {
|
|||
.replace(
|
||||
new RegExp(
|
||||
[
|
||||
`(^|[${util.punctuationCharRange}])(_+)`,
|
||||
`(_+)([${util.punctuationCharRange}]|$)`
|
||||
`(^|[${privateUtil.punctuationCharRange}])(_+)`,
|
||||
`(_+)([${privateUtil.punctuationCharRange}]|$)`
|
||||
].join("|"),
|
||||
"g"
|
||||
),
|
||||
|
@ -113,8 +113,8 @@ function genericPrint(path, options, print) {
|
|||
(prevNode &&
|
||||
prevNode.type === "sentence" &&
|
||||
prevNode.children.length > 0 &&
|
||||
util.getLast(prevNode.children).type === "word" &&
|
||||
!util.getLast(prevNode.children).hasTrailingPunctuation) ||
|
||||
privateUtil.getLast(prevNode.children).type === "word" &&
|
||||
!privateUtil.getLast(prevNode.children).hasTrailingPunctuation) ||
|
||||
(nextNode &&
|
||||
nextNode.type === "sentence" &&
|
||||
nextNode.children.length > 0 &&
|
||||
|
@ -129,7 +129,7 @@ function genericPrint(path, options, print) {
|
|||
case "delete":
|
||||
return concat(["~~", printChildren(path, options, print), "~~"]);
|
||||
case "inlineCode": {
|
||||
const backtickCount = util.getMaxContinuousCount(node.value, "`");
|
||||
const backtickCount = privateUtil.getMaxContinuousCount(node.value, "`");
|
||||
const style = backtickCount === 1 ? "``" : "`";
|
||||
const gap = backtickCount ? " " : "";
|
||||
return concat([style, gap, node.value, gap, style]);
|
||||
|
@ -190,7 +190,10 @@ function genericPrint(path, options, print) {
|
|||
// fenced code block
|
||||
const styleUnit = options.__inJsTemplate ? "~" : "`";
|
||||
const style = styleUnit.repeat(
|
||||
Math.max(3, util.getMaxContinuousCount(node.value, styleUnit) + 1)
|
||||
Math.max(
|
||||
3,
|
||||
privateUtil.getMaxContinuousCount(node.value, styleUnit) + 1
|
||||
)
|
||||
);
|
||||
return concat([
|
||||
style,
|
||||
|
@ -208,7 +211,7 @@ function genericPrint(path, options, print) {
|
|||
case "html": {
|
||||
const parentNode = path.getParentNode();
|
||||
return parentNode.type === "root" &&
|
||||
util.getLast(parentNode.children) === node
|
||||
privateUtil.getLast(parentNode.children) === node
|
||||
? node.value.trimRight()
|
||||
: node.value;
|
||||
}
|
||||
|
@ -428,7 +431,7 @@ function printTable(path, options, print) {
|
|||
const columnMaxWidths = contents.reduce(
|
||||
(currentWidths, rowContents) =>
|
||||
currentWidths.map((width, columnIndex) =>
|
||||
Math.max(width, util.getStringWidth(rowContents[columnIndex]))
|
||||
Math.max(width, privateUtil.getStringWidth(rowContents[columnIndex]))
|
||||
),
|
||||
contents[0].map(() => 3) // minimum width = 3 (---, :--, :-:, --:)
|
||||
);
|
||||
|
@ -482,15 +485,15 @@ function printTable(path, options, print) {
|
|||
}
|
||||
|
||||
function alignLeft(text, width) {
|
||||
return concat([text, " ".repeat(width - util.getStringWidth(text))]);
|
||||
return concat([text, " ".repeat(width - privateUtil.getStringWidth(text))]);
|
||||
}
|
||||
|
||||
function alignRight(text, width) {
|
||||
return concat([" ".repeat(width - util.getStringWidth(text)), text]);
|
||||
return concat([" ".repeat(width - privateUtil.getStringWidth(text)), text]);
|
||||
}
|
||||
|
||||
function alignCenter(text, width) {
|
||||
const spaces = width - util.getStringWidth(text);
|
||||
const spaces = width - privateUtil.getStringWidth(text);
|
||||
const left = Math.floor(spaces / 2);
|
||||
const right = spaces - left;
|
||||
return concat([" ".repeat(left), text, " ".repeat(right)]);
|
||||
|
@ -616,7 +619,7 @@ function shouldRemainTheSameContent(path) {
|
|||
}
|
||||
|
||||
function normalizeDoc(doc) {
|
||||
return util.mapDoc(doc, currentDoc => {
|
||||
return privateUtil.mapDoc(doc, currentDoc => {
|
||||
if (!currentDoc.parts) {
|
||||
return currentDoc;
|
||||
}
|
||||
|
@ -668,7 +671,7 @@ function printTitle(title, options) {
|
|||
|
||||
function normalizeParts(parts) {
|
||||
return parts.reduce((current, part) => {
|
||||
const lastPart = util.getLast(current);
|
||||
const lastPart = privateUtil.getLast(current);
|
||||
|
||||
if (typeof lastPart === "string" && typeof part === "string") {
|
||||
current.splice(-1, 1, lastPart + part);
|
||||
|
@ -699,5 +702,5 @@ module.exports = {
|
|||
print: genericPrint,
|
||||
embed,
|
||||
massageAstNode: clean,
|
||||
hasPrettierIgnore: util.hasIgnoreComment
|
||||
hasPrettierIgnore: privateUtil.hasIgnoreComment
|
||||
};
|
||||
|
|
|
@ -4,7 +4,6 @@ const assert = require("assert");
|
|||
const comments = require("./comments");
|
||||
const FastPath = require("../common/fast-path");
|
||||
const multiparser = require("./multiparser");
|
||||
const util = require("../common/util");
|
||||
|
||||
const doc = require("../doc");
|
||||
const docBuilders = doc.builders;
|
||||
|
@ -75,7 +74,10 @@ function genericPrint(path, options, printPath, args) {
|
|||
|
||||
// Escape hatch
|
||||
if (printer.hasPrettierIgnore && printer.hasPrettierIgnore(path)) {
|
||||
return options.originalText.slice(util.locStart(node), util.locEnd(node));
|
||||
return options.originalText.slice(
|
||||
options.locStart(node),
|
||||
options.locEnd(node)
|
||||
);
|
||||
}
|
||||
|
||||
if (node) {
|
||||
|
|
|
@ -9,20 +9,17 @@ const indent = docBuilders.indent;
|
|||
const lineSuffix = docBuilders.lineSuffix;
|
||||
const join = docBuilders.join;
|
||||
const cursor = docBuilders.cursor;
|
||||
const util = require("../common/util");
|
||||
const privateUtil = require("../common/util");
|
||||
const sharedUtil = require("../common/util-shared");
|
||||
const childNodesCacheKey = Symbol("child-nodes");
|
||||
const locStart = util.locStart;
|
||||
const locEnd = util.locEnd;
|
||||
const getNextNonSpaceNonCommentCharacter =
|
||||
util.getNextNonSpaceNonCommentCharacter;
|
||||
const getNextNonSpaceNonCommentCharacterIndex =
|
||||
util.getNextNonSpaceNonCommentCharacterIndex;
|
||||
|
||||
function getSortedChildNodes(node, text, options, resultArray) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
const printer = options.printer;
|
||||
const locStart = options.locStart;
|
||||
const locEnd = options.locEnd;
|
||||
|
||||
if (resultArray) {
|
||||
if (node && printer.canAttachComment && printer.canAttachComment(node)) {
|
||||
|
@ -82,6 +79,8 @@ function getSortedChildNodes(node, text, options, resultArray) {
|
|||
// .precedingNode, .enclosingNode, and/or .followingNode properties, at
|
||||
// least one of which is guaranteed to be defined.
|
||||
function decorateComment(node, comment, text, options) {
|
||||
const locStart = options.locStart;
|
||||
const locEnd = options.locEnd;
|
||||
const childNodes = getSortedChildNodes(node, text, options);
|
||||
let precedingNode;
|
||||
let followingNode;
|
||||
|
@ -134,17 +133,23 @@ function decorateComment(node, comment, text, options) {
|
|||
comment.enclosingNode.type === "TemplateLiteral"
|
||||
) {
|
||||
const quasis = comment.enclosingNode.quasis;
|
||||
const commentIndex = findExpressionIndexForComment(quasis, comment);
|
||||
const commentIndex = findExpressionIndexForComment(
|
||||
quasis,
|
||||
comment,
|
||||
options
|
||||
);
|
||||
|
||||
if (
|
||||
precedingNode &&
|
||||
findExpressionIndexForComment(quasis, precedingNode) !== commentIndex
|
||||
findExpressionIndexForComment(quasis, precedingNode, options) !==
|
||||
commentIndex
|
||||
) {
|
||||
precedingNode = null;
|
||||
}
|
||||
if (
|
||||
followingNode &&
|
||||
findExpressionIndexForComment(quasis, followingNode) !== commentIndex
|
||||
findExpressionIndexForComment(quasis, followingNode, options) !==
|
||||
commentIndex
|
||||
) {
|
||||
followingNode = null;
|
||||
}
|
||||
|
@ -165,6 +170,8 @@ function attach(comments, ast, text, options) {
|
|||
}
|
||||
|
||||
const tiesToBreak = [];
|
||||
const locStart = options.locStart;
|
||||
const locEnd = options.locEnd;
|
||||
|
||||
comments.forEach((comment, i) => {
|
||||
if (options.parser === "json" && locStart(comment) - locStart(ast) <= 0) {
|
||||
|
@ -180,7 +187,7 @@ function attach(comments, ast, text, options) {
|
|||
|
||||
const isLastComment = comments.length - 1 === i;
|
||||
|
||||
if (util.hasNewline(text, locStart(comment), { backwards: true })) {
|
||||
if (privateUtil.hasNewline(text, locStart(comment), { backwards: true })) {
|
||||
// If a comment exists on its own line, prefer a leading comment.
|
||||
// We also need to check if it's the first line of the file.
|
||||
if (
|
||||
|
@ -189,7 +196,8 @@ function attach(comments, ast, text, options) {
|
|||
precedingNode,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) ||
|
||||
handleMemberExpressionComments(enclosingNode, followingNode, comment) ||
|
||||
handleIfStatementComments(
|
||||
|
@ -197,7 +205,8 @@ function attach(comments, ast, text, options) {
|
|||
precedingNode,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) ||
|
||||
handleTryStatementComments(enclosingNode, followingNode, comment) ||
|
||||
handleClassComments(
|
||||
|
@ -219,10 +228,17 @@ function attach(comments, ast, text, options) {
|
|||
text,
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) ||
|
||||
handleAssignmentPatternComments(enclosingNode, comment) ||
|
||||
handleMethodNameComments(text, enclosingNode, precedingNode, comment)
|
||||
handleMethodNameComments(
|
||||
text,
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
comment,
|
||||
options
|
||||
)
|
||||
) {
|
||||
// We're good
|
||||
} else if (followingNode) {
|
||||
|
@ -237,21 +253,23 @@ function attach(comments, ast, text, options) {
|
|||
/* istanbul ignore next */
|
||||
addDanglingComment(ast, comment);
|
||||
}
|
||||
} else if (util.hasNewline(text, locEnd(comment))) {
|
||||
} else if (privateUtil.hasNewline(text, locEnd(comment))) {
|
||||
if (
|
||||
handleLastFunctionArgComments(
|
||||
text,
|
||||
precedingNode,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) ||
|
||||
handleConditionalExpressionComments(
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
followingNode,
|
||||
comment,
|
||||
text
|
||||
text,
|
||||
options
|
||||
) ||
|
||||
handleImportSpecifierComments(enclosingNode, comment) ||
|
||||
handleIfStatementComments(
|
||||
|
@ -259,7 +277,8 @@ function attach(comments, ast, text, options) {
|
|||
precedingNode,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) ||
|
||||
handleClassComments(
|
||||
enclosingNode,
|
||||
|
@ -296,14 +315,27 @@ function attach(comments, ast, text, options) {
|
|||
precedingNode,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) ||
|
||||
handleObjectPropertyAssignment(enclosingNode, precedingNode, comment) ||
|
||||
handleCommentInEmptyParens(text, enclosingNode, comment) ||
|
||||
handleMethodNameComments(text, enclosingNode, precedingNode, comment) ||
|
||||
handleCommentInEmptyParens(text, enclosingNode, comment, options) ||
|
||||
handleMethodNameComments(
|
||||
text,
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
comment,
|
||||
options
|
||||
) ||
|
||||
handleOnlyComments(enclosingNode, ast, comment, isLastComment) ||
|
||||
handleCommentAfterArrowParams(text, enclosingNode, comment) ||
|
||||
handleFunctionNameComments(text, enclosingNode, precedingNode, comment)
|
||||
handleCommentAfterArrowParams(text, enclosingNode, comment, options) ||
|
||||
handleFunctionNameComments(
|
||||
text,
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
comment,
|
||||
options
|
||||
)
|
||||
) {
|
||||
// We're good
|
||||
} else if (precedingNode && followingNode) {
|
||||
|
@ -316,7 +348,7 @@ function attach(comments, ast, text, options) {
|
|||
if (tieCount > 0) {
|
||||
const lastTie = tiesToBreak[tieCount - 1];
|
||||
if (lastTie.followingNode !== comment.followingNode) {
|
||||
breakTies(tiesToBreak, text);
|
||||
breakTies(tiesToBreak, text, options);
|
||||
}
|
||||
}
|
||||
tiesToBreak.push(comment);
|
||||
|
@ -334,7 +366,7 @@ function attach(comments, ast, text, options) {
|
|||
}
|
||||
});
|
||||
|
||||
breakTies(tiesToBreak, text);
|
||||
breakTies(tiesToBreak, text, options);
|
||||
|
||||
comments.forEach(comment => {
|
||||
// These node references were useful for breaking ties, but we
|
||||
|
@ -346,7 +378,7 @@ function attach(comments, ast, text, options) {
|
|||
});
|
||||
}
|
||||
|
||||
function breakTies(tiesToBreak, text) {
|
||||
function breakTies(tiesToBreak, text, options) {
|
||||
const tieCount = tiesToBreak.length;
|
||||
if (tieCount === 0) {
|
||||
return;
|
||||
|
@ -354,7 +386,7 @@ function breakTies(tiesToBreak, text) {
|
|||
|
||||
const precedingNode = tiesToBreak[0].precedingNode;
|
||||
const followingNode = tiesToBreak[0].followingNode;
|
||||
let gapEndPos = locStart(followingNode);
|
||||
let gapEndPos = options.locStart(followingNode);
|
||||
|
||||
// Iterate backwards through tiesToBreak, examining the gaps
|
||||
// between the tied comments. In order to qualify as leading, a
|
||||
|
@ -371,9 +403,9 @@ function breakTies(tiesToBreak, text) {
|
|||
assert.strictEqual(comment.precedingNode, precedingNode);
|
||||
assert.strictEqual(comment.followingNode, followingNode);
|
||||
|
||||
const gap = text.slice(locEnd(comment), gapEndPos).trim();
|
||||
const gap = text.slice(options.locEnd(comment), gapEndPos).trim();
|
||||
if (gap === "" || /^\(+$/.test(gap)) {
|
||||
gapEndPos = locStart(comment);
|
||||
gapEndPos = options.locStart(comment);
|
||||
} else {
|
||||
// The gap string contained something other than whitespace or open
|
||||
// parentheses.
|
||||
|
@ -461,7 +493,8 @@ function handleIfStatementComments(
|
|||
precedingNode,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) {
|
||||
if (
|
||||
!enclosingNode ||
|
||||
|
@ -476,7 +509,11 @@ function handleIfStatementComments(
|
|||
// if (a /* comment */) {}
|
||||
// The only workaround I found is to look at the next character to see if
|
||||
// it is a ).
|
||||
const nextCharacter = getNextNonSpaceNonCommentCharacter(text, comment);
|
||||
const nextCharacter = privateUtil.getNextNonSpaceNonCommentCharacter(
|
||||
text,
|
||||
comment,
|
||||
options.locEnd
|
||||
);
|
||||
if (nextCharacter === ")") {
|
||||
addTrailingComment(precedingNode, comment);
|
||||
return true;
|
||||
|
@ -552,11 +589,16 @@ function handleConditionalExpressionComments(
|
|||
precedingNode,
|
||||
followingNode,
|
||||
comment,
|
||||
text
|
||||
text,
|
||||
options
|
||||
) {
|
||||
const isSameLineAsPrecedingNode =
|
||||
precedingNode &&
|
||||
!util.hasNewlineInRange(text, locEnd(precedingNode), locStart(comment));
|
||||
!privateUtil.hasNewlineInRange(
|
||||
text,
|
||||
options.locEnd(precedingNode),
|
||||
options.locStart(comment)
|
||||
);
|
||||
|
||||
if (
|
||||
(!precedingNode || !isSameLineAsPrecedingNode) &&
|
||||
|
@ -611,7 +653,13 @@ function handleClassComments(
|
|||
return false;
|
||||
}
|
||||
|
||||
function handleMethodNameComments(text, enclosingNode, precedingNode, comment) {
|
||||
function handleMethodNameComments(
|
||||
text,
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
comment,
|
||||
options
|
||||
) {
|
||||
// This is only needed for estree parsers (flow, typescript) to attach
|
||||
// after a method name:
|
||||
// obj = { fn /*comment*/() {} };
|
||||
|
@ -624,7 +672,11 @@ function handleMethodNameComments(text, enclosingNode, precedingNode, comment) {
|
|||
enclosingNode.key === precedingNode &&
|
||||
// special Property case: { key: /*comment*/(value) };
|
||||
// comment should be attached to value instead of key
|
||||
getNextNonSpaceNonCommentCharacter(text, precedingNode) !== ":"
|
||||
privateUtil.getNextNonSpaceNonCommentCharacter(
|
||||
text,
|
||||
precedingNode,
|
||||
options.locEnd
|
||||
) !== ":"
|
||||
) {
|
||||
addTrailingComment(precedingNode, comment);
|
||||
return true;
|
||||
|
@ -653,9 +705,16 @@ function handleFunctionNameComments(
|
|||
text,
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) {
|
||||
if (getNextNonSpaceNonCommentCharacter(text, comment) !== "(") {
|
||||
if (
|
||||
privateUtil.getNextNonSpaceNonCommentCharacter(
|
||||
text,
|
||||
comment,
|
||||
options.locEnd
|
||||
) !== "("
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -674,12 +733,16 @@ function handleFunctionNameComments(
|
|||
return false;
|
||||
}
|
||||
|
||||
function handleCommentAfterArrowParams(text, enclosingNode, comment) {
|
||||
function handleCommentAfterArrowParams(text, enclosingNode, comment, options) {
|
||||
if (!(enclosingNode && enclosingNode.type === "ArrowFunctionExpression")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const index = getNextNonSpaceNonCommentCharacterIndex(text, comment);
|
||||
const index = sharedUtil.getNextNonSpaceNonCommentCharacterIndex(
|
||||
text,
|
||||
comment,
|
||||
options
|
||||
);
|
||||
if (text.substr(index, 2) === "=>") {
|
||||
addDanglingComment(enclosingNode, comment);
|
||||
return true;
|
||||
|
@ -688,8 +751,14 @@ function handleCommentAfterArrowParams(text, enclosingNode, comment) {
|
|||
return false;
|
||||
}
|
||||
|
||||
function handleCommentInEmptyParens(text, enclosingNode, comment) {
|
||||
if (getNextNonSpaceNonCommentCharacter(text, comment) !== ")") {
|
||||
function handleCommentInEmptyParens(text, enclosingNode, comment, options) {
|
||||
if (
|
||||
privateUtil.getNextNonSpaceNonCommentCharacter(
|
||||
text,
|
||||
comment,
|
||||
options.locEnd
|
||||
) !== ")"
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -727,7 +796,8 @@ function handleLastFunctionArgComments(
|
|||
precedingNode,
|
||||
enclosingNode,
|
||||
followingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) {
|
||||
// Type definitions functions
|
||||
if (
|
||||
|
@ -753,7 +823,11 @@ function handleLastFunctionArgComments(
|
|||
enclosingNode.type === "FunctionDeclaration" ||
|
||||
enclosingNode.type === "ObjectMethod" ||
|
||||
enclosingNode.type === "ClassMethod") &&
|
||||
getNextNonSpaceNonCommentCharacter(text, comment) === ")"
|
||||
privateUtil.getNextNonSpaceNonCommentCharacter(
|
||||
text,
|
||||
comment,
|
||||
options.locEnd
|
||||
) === ")"
|
||||
) {
|
||||
addTrailingComment(precedingNode, comment);
|
||||
return true;
|
||||
|
@ -870,13 +944,14 @@ function handleImportDeclarationComments(
|
|||
text,
|
||||
enclosingNode,
|
||||
precedingNode,
|
||||
comment
|
||||
comment,
|
||||
options
|
||||
) {
|
||||
if (
|
||||
precedingNode &&
|
||||
enclosingNode &&
|
||||
enclosingNode.type === "ImportDeclaration" &&
|
||||
util.hasNewline(text, util.locEnd(comment))
|
||||
privateUtil.hasNewline(text, options.locEnd(comment))
|
||||
) {
|
||||
addTrailingComment(precedingNode, comment);
|
||||
return true;
|
||||
|
@ -924,8 +999,8 @@ function printComment(commentPath, options) {
|
|||
return options.printer.printComment(commentPath, options);
|
||||
}
|
||||
|
||||
function findExpressionIndexForComment(quasis, comment) {
|
||||
const startPos = locStart(comment) - 1;
|
||||
function findExpressionIndexForComment(quasis, comment, options) {
|
||||
const startPos = options.locStart(comment) - 1;
|
||||
|
||||
for (let i = 1; i < quasis.length; ++i) {
|
||||
if (startPos < getQuasiRange(quasis[i]).start) {
|
||||
|
@ -954,14 +1029,16 @@ function printLeadingComment(commentPath, print, options) {
|
|||
if (!contents) {
|
||||
return "";
|
||||
}
|
||||
const isBlock = util.isBlockComment(comment);
|
||||
const isBlock = privateUtil.isBlockComment(comment);
|
||||
|
||||
// Leading block comments should see if they need to stay on the
|
||||
// same line or not.
|
||||
if (isBlock) {
|
||||
return concat([
|
||||
contents,
|
||||
util.hasNewline(options.originalText, locEnd(comment)) ? hardline : " "
|
||||
privateUtil.hasNewline(options.originalText, options.locEnd(comment))
|
||||
? hardline
|
||||
: " "
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -974,7 +1051,7 @@ function printTrailingComment(commentPath, print, options) {
|
|||
if (!contents) {
|
||||
return "";
|
||||
}
|
||||
const isBlock = util.isBlockComment(comment);
|
||||
const isBlock = privateUtil.isBlockComment(comment);
|
||||
|
||||
// We don't want the line to break
|
||||
// when the parentParentNode is a ClassDeclaration/-Expression
|
||||
|
@ -988,7 +1065,7 @@ function printTrailingComment(commentPath, print, options) {
|
|||
parentParentNode.superClass === parentNode;
|
||||
|
||||
if (
|
||||
util.hasNewline(options.originalText, locStart(comment), {
|
||||
privateUtil.hasNewline(options.originalText, options.locStart(comment), {
|
||||
backwards: true
|
||||
})
|
||||
) {
|
||||
|
@ -1004,9 +1081,10 @@ function printTrailingComment(commentPath, print, options) {
|
|||
// if this a comment on its own line; normal trailing comments are
|
||||
// always at the end of another expression.
|
||||
|
||||
const isLineBeforeEmpty = util.isPreviousLineEmpty(
|
||||
const isLineBeforeEmpty = privateUtil.isPreviousLineEmpty(
|
||||
options.originalText,
|
||||
comment
|
||||
comment,
|
||||
options.locStart
|
||||
);
|
||||
|
||||
return lineSuffix(
|
||||
|
@ -1082,7 +1160,12 @@ function printComments(path, print, options, needsSemi) {
|
|||
leadingParts.push(contents);
|
||||
|
||||
const text = options.originalText;
|
||||
if (util.hasNewline(text, util.skipNewline(text, util.locEnd(comment)))) {
|
||||
if (
|
||||
privateUtil.hasNewline(
|
||||
text,
|
||||
privateUtil.skipNewline(text, options.locEnd(comment))
|
||||
)
|
||||
) {
|
||||
leadingParts.push(hardline);
|
||||
}
|
||||
} else if (trailing) {
|
||||
|
|
|
@ -9,7 +9,9 @@ const getPrinter = require("./get-printer");
|
|||
|
||||
const hiddenDefaults = {
|
||||
astFormat: "estree",
|
||||
printer: {}
|
||||
printer: {},
|
||||
locStart: null,
|
||||
locEnd: null
|
||||
};
|
||||
|
||||
// Copy options and fill in default values.
|
||||
|
@ -47,7 +49,10 @@ function normalize(options, opts) {
|
|||
}
|
||||
}
|
||||
|
||||
rawOptions.astFormat = resolveParser(rawOptions).astFormat;
|
||||
const parser = resolveParser(rawOptions);
|
||||
rawOptions.astFormat = parser.astFormat;
|
||||
rawOptions.locEnd = parser.locEnd;
|
||||
rawOptions.locStart = parser.locStart;
|
||||
rawOptions.printer = getPrinter(rawOptions);
|
||||
|
||||
Object.keys(defaults).forEach(k => {
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
const path = require("path");
|
||||
const ConfigError = require("../common/errors").ConfigError;
|
||||
const js = require("../language-js/index.js");
|
||||
|
||||
const locStart = js.locStart;
|
||||
const locEnd = js.locEnd;
|
||||
|
||||
function getParsers(options) {
|
||||
return options.plugins.reduce(
|
||||
|
@ -17,7 +21,9 @@ function resolveParser(opts, parsers) {
|
|||
// Custom parser API always works with JavaScript.
|
||||
return {
|
||||
parse: opts.parser,
|
||||
astFormat: "estree"
|
||||
astFormat: "estree",
|
||||
locStart,
|
||||
locEnd
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -28,7 +34,9 @@ function resolveParser(opts, parsers) {
|
|||
try {
|
||||
return {
|
||||
parse: eval("require")(path.resolve(process.cwd(), opts.parser)),
|
||||
astFormat: "estree"
|
||||
astFormat: "estree",
|
||||
locStart,
|
||||
locEnd
|
||||
};
|
||||
} catch (err) {
|
||||
/* istanbul ignore next */
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
"use strict";
|
||||
|
||||
const sharedUtil = require("../../src/common/util-shared");
|
||||
|
||||
test("shared util has correct structure", () => {
|
||||
expect(typeof sharedUtil.isNextLineEmpty).toEqual("function");
|
||||
expect(typeof sharedUtil.isNextLineEmptyAfterIndex).toEqual("function");
|
||||
expect(typeof sharedUtil.getNextNonSpaceNonCommentCharacterIndex).toEqual(
|
||||
"function"
|
||||
);
|
||||
expect(typeof sharedUtil.mapDoc).toEqual("function");
|
||||
expect(typeof sharedUtil.makeString).toEqual("function");
|
||||
});
|
Loading…
Reference in New Issue