Test: Improve coverage (#8811)

This commit is contained in:
fisker Cheung authored and GitHub committed 2020-08-21 09:43:24 +08:00
1 parent 5a62566cee
commit d31ebf4619
80 files changed
+924 -124

No files matched your search

+2 -6
View File
@@ -19,12 +19,8 @@ module.exports = {
? ["<rootDir>/tests_integration/"]
: [],
collectCoverage: ENABLE_CODE_COVERAGE,
collectCoverageFrom: ["src/**/*.js", "index.js", "!<rootDir>/node_modules/"],
coveragePathIgnorePatterns: [
"<rootDir>/standalone.js",
"<rootDir>/src/document/doc-debug.js",
"<rootDir>/src/main/massage-ast.js",
],
collectCoverageFrom: ["<rootDir>/src/**/*.js", "<rootDir>/bin/**/*.js"],
coveragePathIgnorePatterns: ["<rootDir>/src/document/doc-debug.js"],
coverageReporters: ["text", "lcov"],
moduleNameMapper: {
"prettier/local": "<rootDir>/tests_config/require_prettier.js",
+2
View File
@@ -109,7 +109,9 @@ function* expandPatternsInternal(context) {
try {
result = fastGlob.sync(glob, globOptions);
} catch ({ message }) {
/* istanbul ignore next */
yield { error: `${errorMessages.globError[type]}: ${input}\n${message}` };
/* istanbul ignore next */
continue;
}
+18 -2
View File
@@ -61,6 +61,8 @@ function diff(a, b) {
function handleError(context, filename, error) {
if (error instanceof errors.UndefinedParserError) {
// Can't test on CI, `isTTY()` is always false, see ./is-tty.js
/* istanbul ignore next */
if ((context.argv.write || context.argv["ignore-unknown"]) && isTTY()) {
readline.clearLine(process.stdout, 0);
readline.cursorTo(process.stdout, 0, null);
@@ -96,6 +98,7 @@ function handleError(context, filename, error) {
context.logger.error(`${filename}: ${error.message}`);
} else {
// `invalid.js: Error: Some unexpected error\n[stack trace]`
/* istanbul ignore next */
context.logger.error(filename + ": " + (error.stack || error));
}
@@ -364,7 +367,10 @@ function applyConfigPrecedence(context, options) {
return options || parseArgsToOptions(context);
}
} catch (error) {
/* istanbul ignore next */
context.logger.error(error.toString());
/* istanbul ignore next */
process.exit(2);
}
}
@@ -467,13 +473,19 @@ function formatFiles(context) {
input = fs.readFileSync(filename, "utf8");
} catch (error) {
// Add newline to split errors from filename line.
/* istanbul ignore next */
context.logger.log("");
/* istanbul ignore next */
context.logger.error(
`Unable to read file: ${filename}\n${error.message}`
);
// Don't exit the process if one file failed
/* istanbul ignore next */
process.exitCode = 2;
/* istanbul ignore next */
continue;
}
@@ -514,16 +526,20 @@ function formatFiles(context) {
try {
fs.writeFileSync(filename, output, "utf8");
} catch (error) {
/* istanbul ignore next */
context.logger.error(
`Unable to write file: ${filename}\n${error.message}`
);
// Don't exit the process if one file failed
/* istanbul ignore next */
process.exitCode = 2;
}
} else if (!context.argv.check && !context.argv["list-different"]) {
context.logger.log(`${chalk.grey(filename)} ${Date.now() - start}ms`);
}
} else if (context.argv["debug-check"]) {
/* istanbul ignore else */
if (result.filepath) {
context.logger.log(result.filepath);
} else {
@@ -769,8 +785,6 @@ function createLogger(logLevel) {
switch (logLevel) {
case "silent":
return false;
default:
return true;
case "debug":
if (loggerName === "debug") {
return true;
@@ -804,6 +818,7 @@ function normalizeDetailedOption(name, option) {
deprecated: false,
...(typeof choice === "object" ? choice : { value: choice }),
};
/* istanbul ignore next */
if (newChoice.value === true) {
newChoice.value = ""; // backward compatibility for original boolean option
}
@@ -873,6 +888,7 @@ function createDetailedOptionMap(supportOptions) {
forwardToApi: option.name,
};
/* istanbul ignore next */
if (option.deprecated) {
delete newOption.forwardToApi;
delete newOption.description;
+1
View File
@@ -144,6 +144,7 @@ class FastPath {
let node = this.stack[stackPointer--];
for (const predicate of predicates) {
/* istanbul ignore next */
if (node === undefined) {
return false;
}
+12
View File
@@ -23,6 +23,7 @@ function skip(chars) {
// Allow `skip` functions to be threaded together without having
// to check for failures (did someone say monads?).
/* istanbul ignore next */
if (index === false) {
return false;
}
@@ -76,6 +77,7 @@ const skipEverythingButNewLine = skip(/[^\n\r]/);
* @returns {number | false}
*/
function skipInlineComment(text, index) {
/* istanbul ignore next */
if (index === false) {
return false;
}
@@ -96,6 +98,7 @@ function skipInlineComment(text, index) {
* @returns {number | false}
*/
function skipTrailingComment(text, index) {
/* istanbul ignore next */
if (index === false) {
return false;
}
@@ -123,6 +126,8 @@ function skipNewline(text, index, opts) {
const atIndex = text.charAt(index);
if (backwards) {
// We already replace `\r\n` with `\n` before parsing
/* istanbul ignore next */
if (text.charAt(index - 1) === "\r" && atIndex === "\n") {
return index - 2;
}
@@ -135,6 +140,8 @@ function skipNewline(text, index, opts) {
return index - 1;
}
} else {
// We already replace `\r\n` with `\n` before parsing
/* istanbul ignore next */
if (atIndex === "\r" && text.charAt(index + 1) === "\n") {
return index + 2;
}
@@ -277,6 +284,8 @@ function getNextNonSpaceNonCommentCharacter(text, node, locEnd) {
);
}
// Not using, but it's public utils
/* istanbul ignore next */
/**
* @param {string} text
* @param {number} index
@@ -577,6 +586,7 @@ function addCommentHelper(node, comment) {
// For some reason, TypeScript parses `// x` inside of JSXText as a comment
// We already "print" it via the raw text, we don't need to re-print it as a
// comment
/* istanbul ignore next */
if (node.type === "JSXText") {
comment.printed = true;
}
@@ -603,6 +613,8 @@ function addTrailingComment(node, comment) {
addCommentHelper(node, comment);
}
// Not using
/* istanbul ignore next */
function isWithinParentArrayProperty(path, propertyName) {
const node = path.getValue();
const parent = path.getParentNode();
+5 -6
View File
@@ -4,13 +4,12 @@ const lineColumnToIndex = require("../utils/line-column-to-index");
const { getLast, skipEverythingButNewLine } = require("../common/util");
function calculateLocStart(node, text) {
if (node.source) {
if (typeof node.source.sourceIndex === "number") {
return node.source.sourceIndex; // value-* nodes have this
}
return lineColumnToIndex(node.source.start, text) - 1;
// value-* nodes have this
if (typeof node.sourceIndex === "number") {
return node.sourceIndex;
}
return null;
return node.source ? lineColumnToIndex(node.source.start, text) - 1 : null;
}
function calculateLocEnd(node, text) {
+8
View File
@@ -109,6 +109,7 @@ function parseValueNode(valueNode, options) {
}
parenGroup.close = node;
/* istanbul ignore next */
if (commaGroupStack.length === 1) {
throw new Error("Unbalanced parenthesis");
}
@@ -270,6 +271,7 @@ function parseMediaQuery(params) {
result = mediaParser(params);
} catch (e) {
// Ignore bad media queries
/* istanbul ignore next */
return {
type: "selector-unknown",
value: params,
@@ -294,6 +296,7 @@ function parseNestedCSS(node, options) {
return node;
}
/* istanbul ignore next */
if (!node.raws) {
node.raws = {};
}
@@ -352,10 +355,14 @@ function parseNestedCSS(node, options) {
// Ignore LESS mixin declaration
if (selector.trim().length > 0) {
// TODO: confirm this code is dead
/* istanbul ignore next */
if (selector.startsWith("@") && selector.endsWith(":")) {
return node;
}
// TODO: confirm this code is dead
/* istanbul ignore next */
// Ignore LESS mixins
if (node.mixin) {
node.selector = parseValue(selector, options);
@@ -581,6 +588,7 @@ function parseWithParser(parse, text, options) {
try {
result = parse(text);
} catch (e) {
/* istanbul ignore next */
if (typeof e.line !== "number") {
throw e;
}
+2
View File
@@ -941,6 +941,8 @@ function genericPrint(path, options, print) {
: line,
]);
}
// TODO: confirm this code is dead
/* istanbul ignore next */
case "value-comma": {
return concat([node.value, " "]);
}
+4
View File
@@ -175,6 +175,8 @@ function isURLFunctionNode(node) {
function isLastNode(path, node) {
const parentNode = path.getParentNode();
/* istanbul ignore next */
if (!parentNode) {
return false;
}
@@ -186,6 +188,7 @@ function isDetachedRulesetDeclarationNode(node) {
// If a Less file ends up being parsed with the SCSS parser, Less
// variable declarations will be parsed as atrules with names ending
// with a colon, so keep the original case then.
/* istanbul ignore next */
if (!node.selector) {
return false;
}
@@ -261,6 +264,7 @@ function isSCSSControlDirectiveNode(node) {
}
function isSCSSNestedPropertyNode(node) {
/* istanbul ignore next */
if (!node.selector) {
return false;
}
+1
View File
@@ -66,6 +66,7 @@ function parse(text /*, parsers, opts*/) {
},
});
} else {
/* istanbul ignore next */
throw error;
}
}
+1 -4
View File
@@ -275,10 +275,6 @@ function genericPrint(path, options, print) {
]);
}
case "TypeExtensionDefinition": {
return concat(["extend ", path.call(print, "definition")]);
}
case "ObjectTypeExtension":
case "ObjectTypeDefinition": {
return concat([
@@ -645,6 +641,7 @@ function printComment(commentPath) {
return "#" + comment.value.trimEnd();
}
/* istanbul ignore next */
throw new Error("Not a comment: " + JSON.stringify(comment));
}
+3 -1
View File
@@ -8,9 +8,9 @@ function parse(text, parsers, options) {
let ast;
try {
ast = glimmer(text, { mode: "codemod" });
/* istanbul ignore next */
} catch (error) {
const matches = error.message.match(/on line (\d+)/);
/* istanbul ignore else */
if (matches) {
throw createError(error.message, {
start: { line: Number(matches[1]), column: 0 },
@@ -32,9 +32,11 @@ module.exports = {
// https://prettier.io/docs/en/plugins.html#parsers
// but we need access to the original text to use
// `loc.start` and `loc.end` objects to calculate the offset
/* istanbul ignore next */
locStart(node) {
return node.loc && node.loc.start;
},
/* istanbul ignore next */
locEnd(node) {
return node.loc && node.loc.end;
},
+4
View File
@@ -59,6 +59,7 @@ function ngHtmlParser(
if (options.parser === "vue" && !isVueHtml) {
const shouldParseAsHTML = (node) => {
/* istanbul ignore next */
if (!node) {
return false;
}
@@ -99,6 +100,7 @@ function ngHtmlParser(
const endOffset = endSourceSpan.start.offset;
for (const error of result.errors) {
const { offset } = error.span.start;
/* istanbul ignore next */
if (startOffset < offset && offset < endOffset) {
errors = [error];
break;
@@ -145,6 +147,7 @@ function ngHtmlParser(
} else if (node instanceof Text) {
node.type = "text";
} else {
/* istanbul ignore next */
throw new Error(`Unexpected node ${JSON.stringify(node)}`);
}
};
@@ -299,6 +302,7 @@ function _parse(text, options, parserOptions, shouldParseFrontMatter = true) {
);
const firstText = subAst.children[0];
if (firstText.length === offset) {
/* istanbul ignore next */
subAst.children.shift();
} else {
firstText.sourceSpan = new ParseSourceSpan(
+7 -18
View File
@@ -78,21 +78,11 @@ function embed(path, print, textToDoc, options) {
return;
}
let doc;
try {
doc = textToDoc(
htmlTrimPreserveIndentation(getNodeContent(node, options)),
{ parser },
{ stripTrailingHardline: true }
);
} catch (_) {
return;
}
// `textToDoc` don't throw on `production` mode
if (!doc) {
return;
}
const doc = textToDoc(
htmlTrimPreserveIndentation(getNodeContent(node, options)),
{ parser },
{ stripTrailingHardline: true }
);
return concat([
printOpeningTagPrefix(node, options),
@@ -446,10 +436,8 @@ function genericPrint(path, options, print) {
]),
]);
}
case "yaml":
case "toml":
return concat(replaceEndOfLineWith(node.raw, literalline));
default:
/* istanbul ignore next */
throw new Error(`Unexpected node type ${node.type}`);
}
}
@@ -957,6 +945,7 @@ function printOpeningTagEndMarker(node) {
function printClosingTagStartMarker(node, options) {
assert(!node.isSelfClosing);
/* istanbul ignore next */
if (shouldNotPrintClosingTag(node, options)) {
return "";
}
+3 -8
View File
@@ -92,10 +92,12 @@ function shouldPreserveContent(node, options) {
}
function hasPrettierIgnore(node) {
/* istanbul ignore next */
if (node.type === "attribute") {
return false;
}
/* istanbul ignore next */
if (!node.parent) {
return false;
}
@@ -429,8 +431,6 @@ function inferScriptParser(node, options) {
getParserName(node.attrMap.lang, options)
);
}
return null;
}
function isBlockLikeCssDisplay(cssDisplay) {
@@ -465,7 +465,7 @@ function isPreLikeNode(node) {
return getNodeCssStyleWhiteSpace(node).startsWith("pre");
}
function countParents(path, predicate = () => true) {
function countParents(path, predicate) {
let counter = 0;
for (let i = path.stack.length - 1; i >= 0; i--) {
const value = path.stack[i];
@@ -591,10 +591,6 @@ function dedentString(text, minIndent = getMinIndentation(text)) {
.join("\n");
}
function identity(x) {
return x;
}
function shouldNotPrintClosingTag(node, options) {
return (
!node.isSelfClosing &&
@@ -661,7 +657,6 @@ module.exports = {
getNodeCssStyleWhiteSpace,
getPrettierIgnoreAttributeCommentData,
hasPrettierIgnore,
identity,
inferScriptParser,
isVueCustomBlock,
isVueNonHtmlBlock,
-32
View File
@@ -54,38 +54,6 @@ function clean(ast, newObj, parent) {
return null;
}
// (TypeScript) Ignore `static` in `constructor(static p) {}`
// and `export` in `constructor(export p) {}`
if (
ast.type === "TSParameterProperty" &&
ast.accessibility === null &&
!ast.readonly
) {
return {
type: "Identifier",
name: ast.parameter.name,
typeAnnotation: newObj.parameter.typeAnnotation,
decorators: newObj.decorators,
};
}
// (TypeScript) ignore empty `specifiers` array
if (
ast.type === "TSNamespaceExportDeclaration" &&
ast.specifiers &&
ast.specifiers.length === 0
) {
delete newObj.specifiers;
}
// We convert <div></div> to <div />
if (ast.type === "JSXOpeningElement") {
delete newObj.selfClosing;
}
if (ast.type === "JSXElement") {
delete newObj.closingElement;
}
// We change {'key': value} into {key: value}.
// And {key: value} into {'key': value}.
// Also for (some) number keys.
+1
View File
@@ -19,6 +19,7 @@ function parse(text, parsers, opts) {
// suppose our guess is correct
const e = firstError;
/* istanbul ignore next */
if (typeof e.lineNumber === "undefined") {
throw e;
}
+1
View File
@@ -323,6 +323,7 @@ function printMemberChain(path, options, print) {
}
function printIndentedGroup(groups) {
/* istanbul ignore next */
if (groups.length === 0) {
return "";
}
+3
View File
@@ -3999,6 +3999,7 @@ function shouldPrintParamsWithoutParens(path, options) {
}
// Fallback default; should be unreachable
/* istanbul ignore next */
return false;
}
@@ -4757,6 +4758,7 @@ function printJSXElement(path, options, print) {
function maybeWrapJSXElementInParens(path, elem, options) {
const parent = path.getParentNode();
/* istanbul ignore next */
if (!parent) {
return elem;
}
@@ -5285,6 +5287,7 @@ function printComment(commentPath, options) {
.slice(options.locStart(comment), options.locEnd(comment))
.trimEnd();
default:
/* istanbul ignore next */
throw new Error("Not a comment: " + JSON.stringify(comment));
}
}
+1 -1
View File
@@ -868,7 +868,7 @@ function isLastStatement(path) {
const body = (parent.body || parent.consequent).filter(
(stmt) => stmt.type !== "EmptyStatement"
);
return body && body[body.length - 1] === node;
return body[body.length - 1] === node;
}
/**
+1
View File
@@ -27,6 +27,7 @@ const printers = {
};
const parsers = {
/* istanbul ignore next */
get remark() {
return require("./parser-markdown").parsers.remark;
},
+1
View File
@@ -45,6 +45,7 @@ const tokenizeEsSyntax = (eat, value) => {
}
};
/* istanbul ignore next */
tokenizeEsSyntax.locator = (value /*, fromIndex*/) => {
return isExport(value) || isImport(value) ? -1 : 1;
};
+6 -6
View File
@@ -258,12 +258,6 @@ function genericPrint(path, options, print) {
style,
]);
}
case "yaml":
case "toml":
return options.originalText.slice(
node.position.start.offset,
node.position.end.offset
);
case "html": {
const parentNode = path.getParentNode();
const value =
@@ -385,6 +379,9 @@ function genericPrint(path, options, print) {
])
);
}
// `footnote` requires `.use(footnotes, {inlineNotes: true})`, we are not using this option
// https://github.com/remarkjs/remark-footnotes#optionsinlinenotes
/* istanbul ignore next */
case "footnote":
return concat(["[^", printChildren(path, options, print), "]"]);
case "footnoteReference":
@@ -463,6 +460,7 @@ function genericPrint(path, options, print) {
case "tableRow": // handled in "table"
case "listItem": // handled in "list"
default:
/* istanbul ignore next */
throw new Error(`Unknown markdown type ${JSON.stringify(node.type)}`);
}
}
@@ -768,6 +766,8 @@ function printChildren(path, options, print, events) {
if (!shouldNotPrePrintHardline(childNode, data)) {
parts.push(hardline);
// Can't find a case to pass `shouldPrePrintTripleHardline`
/* istanbul ignore next */
if (lastChildNode && TRAILING_HARDLINE_NODES.has(lastChildNode.type)) {
if (shouldPrePrintTripleHardline(childNode, data)) {
parts.push(hardline);
+13 -6
View File
@@ -17,10 +17,12 @@ function parse(text) {
return root;
} catch (error) {
// istanbul ignore next
throw error && error.position
? createError(error.message, error.position)
: error;
if (error && error.position) {
throw createError(error.message, error.position);
}
/* istanbul ignore next */
throw error;
}
}
@@ -28,8 +30,13 @@ const parser = {
astFormat: "yaml",
parse,
hasPragma,
locStart: (node) => node.position.start.offset,
locEnd: (node) => node.position.end.offset,
locStart(node) {
return node.position.start.offset;
},
/* istanbul ignore next */
locEnd(node) {
return node.position.end.offset;
},
};
module.exports = {
+2
View File
@@ -551,6 +551,7 @@ function align(n, doc) {
}
function isInlineNode(node) {
/* istanbul ignore next */
if (!node) {
return true;
}
@@ -569,6 +570,7 @@ function isInlineNode(node) {
}
function isSingleLineNode(node) {
/* istanbul ignore next */
if (!node) {
return true;
}
+2
View File
@@ -165,6 +165,7 @@ function splitWithSingleSpace(text) {
let lastPart;
for (const part of text.split(/( +)/g)) {
/* istanbul ignore else */
if (part !== " ") {
if (lastPart === " ") {
parts.push(part);
@@ -178,6 +179,7 @@ function splitWithSingleSpace(text) {
lastPart = part;
}
/* istanbul ignore next */
if (lastPart === " ") {
parts.push((parts.pop() || "") + " ");
}
+3
View File
@@ -381,6 +381,7 @@ function findExpressionIndexForComment(quasis, comment, options) {
function printLeadingComment(commentPath, options) {
const comment = commentPath.getValue();
const contents = printComment(commentPath, options);
/* istanbul ignore next */
if (!contents) {
return "";
}
@@ -407,6 +408,7 @@ function printLeadingComment(commentPath, options) {
function printTrailingComment(commentPath, options) {
const comment = commentPath.getValue();
const contents = printComment(commentPath, options);
/* istanbul ignore next */
if (!contents) {
return "";
}
@@ -502,6 +504,7 @@ function printComments(path, print, options, needsSemi) {
if (leading) {
const contents = printLeadingComment(commentPath, options);
/* istanbul ignore next */
if (!contents) {
return;
}
+1
View File
@@ -274,6 +274,7 @@ function format(text, opts) {
if (!hasCursor) {
opts.cursorOffset = -1;
}
/* istanbul ignore next */
if (opts.rangeStart < 0) {
opts.rangeStart = 0;
}
+1
View File
@@ -71,6 +71,7 @@ function textToDoc(
return stripTrailingHardline(doc, true);
}
/* istanbul ignore next */
return doc;
}
+3
View File
@@ -161,6 +161,7 @@ function optionInfoToSchema(optionInfo, { isCLI, optionInfos }) {
SchemaConstructor = vnopts.StringSchema;
break;
default:
/* istanbul ignore next */
throw new Error(`Unexpected type ${optionInfo.type}`);
}
@@ -174,6 +175,7 @@ function optionInfoToSchema(optionInfo, { isCLI, optionInfos }) {
};
}
/* istanbul ignore next */
if (optionInfo.redirect) {
handlers.redirect = (value) =>
!value
@@ -186,6 +188,7 @@ function optionInfoToSchema(optionInfo, { isCLI, optionInfos }) {
};
}
/* istanbul ignore next */
if (optionInfo.deprecated) {
handlers.deprecated = true;
}
+6
View File
@@ -105,12 +105,16 @@ function normalize(options, opts) {
function getPlugin(options) {
const { astFormat } = options;
// TODO: test this with plugins
/* istanbul ignore next */
if (!astFormat) {
throw new Error("getPlugin() requires astFormat to be set");
}
const printerPlugin = options.plugins.find(
(plugin) => plugin.printers && plugin.printers[astFormat]
);
// TODO: test this with plugins
/* istanbul ignore next */
if (!printerPlugin) {
throw new Error(`Couldn't find plugin for AST format "${astFormat}"`);
}
@@ -119,6 +123,7 @@ function getPlugin(options) {
}
function getInterpreter(filepath) {
/* istanbul ignore next */
if (typeof filepath !== "string") {
return "";
}
@@ -150,6 +155,7 @@ function getInterpreter(filepath) {
} catch (err) {
// There are some weird cases where paths are missing, causing Jest
// failures. It's unclear what these correspond to in the real world.
/* istanbul ignore next */
return "";
} finally {
try {
+14 -12
View File
@@ -13,6 +13,8 @@ const ownDescriptor = Object.getOwnPropertyDescriptor;
function getParsers(options) {
const parsers = {};
for (const plugin of options.plugins) {
// TODO: test this with plugins
/* istanbul ignore next */
if (!plugin.parsers) {
continue;
}
@@ -48,18 +50,18 @@ function resolveParser(opts, parsers) {
throw new ConfigError(
`Couldn't resolve parser "${opts.parser}". Parsers must be explicitly added to the standalone bundle.`
);
} else {
try {
return {
parse: eval("require")(path.resolve(process.cwd(), opts.parser)),
astFormat: "estree",
locStart,
locEnd,
};
} catch (err) {
/* istanbul ignore next */
throw new ConfigError(`Couldn't resolve parser "${opts.parser}"`);
}
}
try {
return {
parse: eval("require")(path.resolve(process.cwd(), opts.parser)),
astFormat: "estree",
locStart,
locEnd,
};
} catch (err) {
/* istanbul ignore next */
throw new ConfigError(`Couldn't resolve parser "${opts.parser}"`);
}
}
}
+1
View File
@@ -109,6 +109,7 @@ const graphqlSourceElements = new Set([
"ScalarTypeDefinition",
]);
function isSourceElement(opts, node) {
/* istanbul ignore next */
if (node == null) {
return false;
}
+2 -17
View File
@@ -2,8 +2,7 @@
const escape = require("escape-string-regexp");
const {
builders: { hardline, literalline, concat, markAsRoot },
utils: { mapDoc },
builders: { hardline, concat, markAsRoot },
} = require("../document");
const DELIMITER_MAP = {
@@ -46,9 +45,7 @@ function print(node, textToDoc) {
if (node.lang === "yaml") {
const value = node.value.trim();
const doc = value
? replaceNewlinesWithLiterallines(
textToDoc(value, { parser: "yaml" }, { stripTrailingHardline: true })
)
? textToDoc(value, { parser: "yaml" }, { stripTrailingHardline: true })
: "";
return markAsRoot(
concat(["---", hardline, doc, doc ? hardline : "", "---"])
@@ -56,16 +53,4 @@ function print(node, textToDoc) {
}
}
function replaceNewlinesWithLiterallines(doc) {
return mapDoc(doc, (currentDoc) =>
typeof currentDoc === "string" && currentDoc.includes("\n")
? concat(
currentDoc
.split(/(\n)/g)
.map((v, i) => (i % 2 === 0 ? v : literalline))
)
: currentDoc
);
}
module.exports = { parse, print };
-3
View File
@@ -5,9 +5,6 @@ module.exports = function (lineColumn, text) {
let index = 0;
for (let i = 0; i < lineColumn.line - 1; ++i) {
index = text.indexOf("\n", index) + 1;
if (index === -1) {
return -1;
}
}
return index + lineColumn.column;
};
@@ -0,0 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`type-extendsion-syntax.graphql format 1`] = `
====================================options=====================================
parsers: ["graphql"]
printWidth: 80
| printWidth
=====================================input======================================
type User {
name: String
birthday: Int
}
extend type User {
age: Int
}
=====================================output=====================================
type User {
name: String
birthday: Int
}
extend type User {
age: Int
}
================================================================================
`;
@@ -0,0 +1 @@
run_spec(__dirname, ["graphql"]);
@@ -0,0 +1,8 @@
type User {
name: String
birthday: Int
}
extend type User {
age: Int
}
@@ -8,8 +8,17 @@ printWidth: 80
=====================================input======================================
<span><![CDATA[<sender>John Smith</sender>]]></span>
<span><![CDATA[1]]> a <![CDATA[2]]></span>
<span><![CDATA[1]]> <br> <![CDATA[2]]></span>
=====================================output=====================================
<span><![CDATA[<sender>John Smith</sender>]]></span>
<span><![CDATA[1]]> a <![CDATA[2]]></span>
<span
><![CDATA[1]]> <br />
<![CDATA[2]]></span
>
================================================================================
`;
+3
View File
@@ -1 +1,4 @@
<span><![CDATA[<sender>John Smith</sender>]]></span>
<span><![CDATA[1]]> a <![CDATA[2]]></span>
<span><![CDATA[1]]> <br> <![CDATA[2]]></span>
@@ -0,0 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`invalid.html format 1`] = `
====================================options=====================================
parsers: ["html"]
printWidth: 80
| printWidth
=====================================input======================================
<img src="a"
srcset="
should-not-format 400w 100h,
should-not-format 500w 200h
"
alt=""/>
<img src="a"
srcset="
should-not-format ,, should-not-format 0q,,,
"
alt=""/>
=====================================output=====================================
<img
src="a"
srcset="
should-not-format 400w 100h,
should-not-format 500w 200h
"
alt=""
/>
<img
src="a"
srcset="
should-not-format ,, should-not-format 0q,,,
"
alt=""
/>
================================================================================
`;
+12
View File
@@ -0,0 +1,12 @@
<img src="a"
srcset="
should-not-format 400w 100h,
should-not-format 500w 200h
"
alt=""/>
<img src="a"
srcset="
should-not-format ,, should-not-format 0q,,,
"
alt=""/>
+1
View File
@@ -0,0 +1 @@
run_spec(__dirname, ["html"]);
@@ -16,6 +16,32 @@ printWidth: 80
================================================================================
`;
exports[`snippet: cursor-and-range.js format 1`] = `
====================================options=====================================
parsers: ["babel"]
printWidth: 80
| | printWidth
=====================================input======================================
1 | 
2 |
> 3 | class a {
| ^^^^
> 4 | b( <|> ) {}
| ^^^^^^^^^^^^^^
5 | }
6 |
7 | let x
=====================================output=====================================

class a {
b(<|>) {}
}
let x
================================================================================
`;
exports[`snippet: range-1.js format 1`] = `
====================================options=====================================
parsers: ["babel"]
@@ -69,6 +69,115 @@ printWidth: 80
================================================================================
`;
exports[`cursor-and-range.js - {"endOfLine":"auto"} format 1`] = `
====================================options=====================================
endOfLine: "auto"
parsers: ["babel"]
printWidth: 80
| | printWidth
=====================================input======================================
1 | <LF>
2 | <LF>
> 3 | class a {<LF>
| ^^^^<LF>
> 4 | b( <|> ) {}<LF>
| ^^^^^^^^^^^^^^<LF>
5 | }<LF>
6 | <LF>
7 | let x
=====================================output=====================================
** The EOL of output might not real when \`TEST_CRLF\` **
<LF>
<LF>
class a {<LF>
b(<|>) {}<LF>
}<LF>
<LF>
let x
================================================================================
`;
exports[`cursor-and-range.js - {"endOfLine":"cr"} format 1`] = `
====================================options=====================================
endOfLine: "cr"
parsers: ["babel"]
printWidth: 80
| | printWidth
=====================================input======================================
1 | <LF>
2 | <LF>
> 3 | class a {<LF>
| ^^^^<LF>
> 4 | b( <|> ) {}<LF>
| ^^^^^^^^^^^^^^<LF>
5 | }<LF>
6 | <LF>
7 | let x
=====================================output=====================================
<CR>
<CR>
class a {<CR>
b(<|>) {}<CR>
}<CR>
<CR>
let x
================================================================================
`;
exports[`cursor-and-range.js - {"endOfLine":"crlf"} format 1`] = `
====================================options=====================================
endOfLine: "crlf"
parsers: ["babel"]
printWidth: 80
| | printWidth
=====================================input======================================
1 | <LF>
2 | <LF>
> 3 | class a {<LF>
| ^^^^<LF>
> 4 | b( <|> ) {}<LF>
| ^^^^^^^^^^^^^^<LF>
5 | }<LF>
6 | <LF>
7 | let x
=====================================output=====================================
<CRLF>
<CRLF>
class a {<CRLF>
b(<|>) {}<CRLF>
}<CRLF>
<CRLF>
let x
================================================================================
`;
exports[`cursor-and-range.js - {"endOfLine":"lf"} format 1`] = `
====================================options=====================================
endOfLine: "lf"
parsers: ["babel"]
printWidth: 80
| | printWidth
=====================================input======================================
1 | <LF>
2 | <LF>
> 3 | class a {<LF>
| ^^^^<LF>
> 4 | b( <|> ) {}<LF>
| ^^^^^^^^^^^^^^<LF>
5 | }<LF>
6 | <LF>
7 | let x
=====================================output=====================================
<LF>
<LF>
class a {<LF>
b(<|>) {}<LF>
}<LF>
<LF>
let x
================================================================================
`;
exports[`range-1.js - {"endOfLine":"auto"} format 1`] = `
====================================options=====================================
endOfLine: "auto"
+7
View File
@@ -0,0 +1,7 @@
class <<<PRETTIER_RANGE_START>>> a {
b( <|> ) {}<<<PRETTIER_RANGE_END>>>
}
let x
@@ -1,5 +1,29 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`array.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| | printWidth
=====================================input======================================
1 | a = [
2 | ,
> 3 | ,,,,
| ^^^^
> 4 |
| ^
> 5 | ,
| ^
> 6 |
| ^
7 | ,
8 | a,
9 | ]
=====================================output=====================================
a = [, , , , , , , a];
================================================================================
`;
exports[`class-declaration.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
+9
View File
@@ -0,0 +1,9 @@
a = [
,
<<<PRETTIER_RANGE_START>>>,,,,
,
<<<PRETTIER_RANGE_END>>>
,
a,
]
@@ -1,5 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`footnote.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
printWidth: 80
proseWrap: "always"
| printWidth
=====================================input======================================
^[inline]
=====================================output=====================================
^[inline]
================================================================================
`;
exports[`simple.md - {"proseWrap":"always"} format 1`] = `
====================================options=====================================
parsers: ["markdown"]
+1
View File
@@ -0,0 +1 @@
^[inline]
@@ -1,5 +1,121 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`front-matter-toml.html - {"embeddedLanguageFormatting":"off"} format 1`] = `
====================================options=====================================
embeddedLanguageFormatting: "off"
parsers: ["html"]
printWidth: 80
| printWidth
=====================================input======================================
+++
title: Hello
slug: home
+++
<h1>
Hello world!</h1>
=====================================output=====================================
+++
title: Hello
slug: home
+++
<h1>Hello world!</h1>
================================================================================
`;
exports[`front-matter-toml.html format 1`] = `
====================================options=====================================
parsers: ["html"]
printWidth: 80
| printWidth
=====================================input======================================
+++
title: Hello
slug: home
+++
<h1>
Hello world!</h1>
=====================================output=====================================
+++
title: Hello
slug: home
+++
<h1>Hello world!</h1>
================================================================================
`;
exports[`front-matter-yaml.html - {"embeddedLanguageFormatting":"off"} format 1`] = `
====================================options=====================================
embeddedLanguageFormatting: "off"
parsers: ["html"]
printWidth: 80
| printWidth
=====================================input======================================
---yaml
title: Hello
slug: home
---
<h1>
Hello world!</h1>
=====================================output=====================================
---yaml
title: Hello
slug: home
---
<h1>Hello world!</h1>
================================================================================
`;
exports[`front-matter-yaml.html format 1`] = `
====================================options=====================================
parsers: ["html"]
printWidth: 80
| printWidth
=====================================input======================================
---yaml
title: Hello
slug: home
---
<h1>
Hello world!</h1>
=====================================output=====================================
---
title: Hello
slug: home
---
<h1>Hello world!</h1>
================================================================================
`;
exports[`test.html - {"embeddedLanguageFormatting":"off"} format 1`] = `
====================================options=====================================
embeddedLanguageFormatting: "off"
@@ -0,0 +1,9 @@
+++
title: Hello
slug: home
+++
<h1>
Hello world!</h1>
@@ -0,0 +1,9 @@
---yaml
title: Hello
slug: home
---
<h1>
Hello world!</h1>
@@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`invalid.hbs error test 1`] = `
"Parse error on line 2:
<A >x, {{@name}
--------------^
Expecting 'CLOSE_RAW_BLOCK', 'CLOSE', 'CLOSE_UNESCAPED', 'OPEN_SEXPR', 'CLOSE_SEXPR', 'ID', 'OPEN_BLOCK_PARAMS', 'STRING', 'NUMBER', 'BOOLEAN', 'UNDEFINED', 'NULL', 'DATA', 'SEP', got 'INVALID' (2:0)
1 | <A >
> 2 | x, {{@name}
3 | "
`;
+2
View File
@@ -0,0 +1,2 @@
<A >
x, {{@name}
@@ -0,0 +1 @@
run_spec(__dirname, ["glimmer"]);
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`inline-comment.js error test 1`] = `
exports[`inline-comment.less error test 1`] = `
"(postcss) CssSyntaxError Unknown word (5:4)
3 | a{
4 | prop
@@ -10,3 +10,21 @@ exports[`inline-comment.js error test 1`] = `
7 | value;
8 | }"
`;
exports[`open-double-quote.less error test 1`] = `
"(postcss) CssSyntaxError Unclosed string (2:17)
1 | a {
> 2 | background: url(\\"
| ^
3 | }
4 | "
`;
exports[`open-sigle-quote.less error test 1`] = `
"(postcss) CssSyntaxError Unclosed string (2:17)
1 | a {
> 2 | background: url('
| ^
3 | }
4 | "
`;
@@ -0,0 +1,3 @@
a {
background: url("
}
@@ -0,0 +1,3 @@
a {
background: url('
}
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`invalid.vue format 1`] = `
====================================options=====================================
parsers: ["vue"]
printWidth: 80
| printWidth
=====================================input======================================
<template>
<div
v-for=" item instanceof items "
></div>
</template>
=====================================output=====================================
<template>
<div v-for=" item instanceof items "></div>
</template>
================================================================================
`;
+5
View File
@@ -0,0 +1,5 @@
<template>
<div
v-for=" item instanceof items "
></div>
</template>
+1
View File
@@ -0,0 +1 @@
run_spec(__dirname, ["vue"]);
@@ -41,6 +41,10 @@ semi: false
"
@click="doSomething()"
@click="doSomething;"
@click="a.b;"
@click="a[1];"
@click="a['b'];"
@click="a[null];"
#default="{foo:{bar:{baz}}}"
></div>
</template>
@@ -104,6 +108,10 @@ semi: false
"
@click="doSomething()"
@click="doSomething;"
@click="a.b;"
@click="a[1];"
@click="a['b'];"
@click="a[null]"
#default="{ foo: { bar: { baz } } }"
></div>
</template>
@@ -152,6 +160,10 @@ trailingComma: "none"
"
@click="doSomething()"
@click="doSomething;"
@click="a.b;"
@click="a[1];"
@click="a['b'];"
@click="a[null];"
#default="{foo:{bar:{baz}}}"
></div>
</template>
@@ -215,6 +227,10 @@ trailingComma: "none"
"
@click="doSomething()"
@click="doSomething;"
@click="a.b;"
@click="a[1];"
@click="a['b'];"
@click="a[null]"
#default="{ foo: { bar: { baz } } }"
></div>
</template>
@@ -262,6 +278,10 @@ printWidth: 80
"
@click="doSomething()"
@click="doSomething;"
@click="a.b;"
@click="a[1];"
@click="a['b'];"
@click="a[null];"
#default="{foo:{bar:{baz}}}"
></div>
</template>
@@ -325,6 +345,10 @@ printWidth: 80
"
@click="doSomething()"
@click="doSomething;"
@click="a.b;"
@click="a[1];"
@click="a['b'];"
@click="a[null]"
#default="{ foo: { bar: { baz } } }"
></div>
</template>
+4
View File
@@ -32,6 +32,10 @@
"
@click="doSomething()"
@click="doSomething;"
@click="a.b;"
@click="a[1];"
@click="a['b'];"
@click="a[null];"
#default="{foo:{bar:{baz}}}"
></div>
</template>
@@ -38,8 +38,12 @@ exports[`throw error for unsupported extension (write) 1`] = `Array []`;
exports[`throw error with invalid config format (stdout) 1`] = `""`;
exports[`throw error with invalid config format (stdout) 2`] = `""`;
exports[`throw error with invalid config format (write) 1`] = `Array []`;
exports[`throw error with invalid config format (write) 2`] = `Array []`;
exports[`throw error with invalid config option (int) (stderr) 1`] = `
"[error] Invalid tabWidth value. Expected an integer, but received 0.5.
"
@@ -0,0 +1,16 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`API prettier.formatDoc 1`] = `
"[
group([
\\"const\\",
\\" \\",
group([\\"foo\\", \\" =\\", group(indent([line, '\\"bar\\"']))]),
indent([]),
\\";\\",
]),
hardline,
breakParent,
];
"
`;
@@ -135,3 +135,13 @@ exports[`file-info should try resolve config (stdout) 1`] = `
`;
exports[`file-info should try resolve config (write) 1`] = `Array []`;
exports[`non-exists ignore path (stderr) 1`] = `""`;
exports[`non-exists ignore path (stdout) 1`] = `
"{ \\"ignored\\": false, \\"inferredParser\\": \\"babel\\" }
"
`;
exports[`non-exists ignore path (write) 1`] = `Array []`;
@@ -1,5 +1,27 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apply editorconfig for stdin-filepath with a deep path (stderr) 1`] = `""`;
exports[`apply editorconfig for stdin-filepath with a deep path (stderr) 2`] = `""`;
exports[`apply editorconfig for stdin-filepath with a deep path (stdout) 1`] = `
"function f() {
console.log(\\"should be indented with a tab\\")
}
"
`;
exports[`apply editorconfig for stdin-filepath with a deep path (stdout) 2`] = `
"function f() {
console.log(\\"should be indented with a tab\\")
}
"
`;
exports[`apply editorconfig for stdin-filepath with a deep path (write) 1`] = `Array []`;
exports[`apply editorconfig for stdin-filepath with a deep path (write) 2`] = `Array []`;
exports[`apply editorconfig for stdin-filepath with nonexistent directory (stderr) 1`] = `""`;
exports[`apply editorconfig for stdin-filepath with nonexistent directory (stdout) 1`] = `
@@ -22,6 +22,18 @@ describe("throw error with invalid config format", () => {
});
});
describe("throw error with invalid config format", () => {
runPrettier("cli/config/invalid", [
"--config",
"type-error/.prettierrc",
]).test({
status: "non-zero",
stderr: expect.stringMatching(
"Config is only allowed to be an object, but received number in"
),
});
});
describe("throw error with invalid config target (directory)", () => {
runPrettier("cli/config/invalid", [
"--config",
@@ -249,6 +249,35 @@ test("API resolveConfig.sync overrides work with absolute paths", () => {
});
});
test("API resolveConfig.sync overrides excludeFiles", () => {
const notOverride = path.join(
__dirname,
"../cli/config/overrides-exclude-files/foo"
);
expect(prettier.resolveConfig.sync(notOverride)).toMatchObject({
singleQuote: true,
trailingComma: "all",
});
const singleQuote = path.join(
__dirname,
"../cli/config/overrides-exclude-files/single-quote.js"
);
expect(prettier.resolveConfig.sync(singleQuote)).toMatchObject({
singleQuote: true,
trailingComma: "es5",
});
const doubleQuote = path.join(
__dirname,
"../cli/config/overrides-exclude-files/double-quote.js"
);
expect(prettier.resolveConfig.sync(doubleQuote)).toMatchObject({
singleQuote: false,
trailingComma: "es5",
});
});
test("API resolveConfig removes $schema option", () => {
const file = path.resolve(
path.join(__dirname, "../cli/config/$schema/index.js")
+44
View File
@@ -0,0 +1,44 @@
"use strict";
const {
parse,
formatAST,
formatDoc,
printToDoc,
printDocToString,
} = require("prettier/local").__debug;
const { outdent } = require("outdent");
const code = outdent`
const foo = 'bar'
`;
const formatted = 'const foo = "bar";\n';
const options = { parser: "babel", originalText: code };
describe("API", () => {
const { ast } = parse(code, options);
test("prettier.parse", () => {
expect(Array.isArray(ast.program.body)).toBe(true);
});
const { formatted: formatResultFromAST } = formatAST(ast, options);
test("prettier.formatAST", () => {
expect(formatResultFromAST).toBe(formatted);
});
const doc = printToDoc(code, options);
test("prettier.printToDoc", () => {
expect(doc.type).toBe("concat");
expect(Array.isArray(doc.parts)).toBe(true);
});
const formatResultFromDoc = formatDoc(doc, options);
test("prettier.formatDoc", () => {
expect(formatResultFromDoc).toMatchSnapshot();
});
const { formatted: stringFromDoc } = printDocToString(doc, options);
test("prettier.printDocToString", () => {
expect(stringFromDoc).toBe(formatted);
});
});
+10
View File
@@ -62,6 +62,16 @@ describe("extracts file-info with ignored=true for a file in a hand-picked .pret
});
});
describe("non-exists ignore path", () => {
runPrettier("cli/", [
"--file-info",
"regular-module.js",
"--ignore-path=ignore-path/non-exists/.prettierignore",
]).test({
status: 0,
});
});
describe("extracts file-info for a file in not_node_modules", () => {
runPrettier("cli/with-node-modules/", [
"--file-info",
@@ -1,5 +1,7 @@
"use strict";
const path = require("path");
const prettier = require("prettier/local");
const runPrettier = require("../runPrettier");
expect.addSnapshotSerializer(require("../path-serializer"));
@@ -8,4 +10,15 @@ describe("throw error with invalid ignore", () => {
runPrettier("cli/invalid-ignore", ["something.js"]).test({
status: "non-zero",
});
test("sync api", async () => {
await expect(
prettier.getFileInfo("something.js", {
ignorePath: path.join(
__dirname,
"../cli/invalid-ignore/.prettierignore"
),
})
).rejects.toThrow(/EISDIR: illegal operation on a directory/);
});
});
@@ -54,3 +54,18 @@ describe("external options from config file should work", () => {
write: [],
});
});
describe("Non exists plugin", () => {
runPrettier(
"plugins/options-string",
["--plugin=--invalid--", "--stdin-filepath", "example.foo"],
{ input: "hello-world" }
).test({
stdout: "",
stderr: expect.stringMatching(
/Cannot (?:resolve|find) module '--invalid--' from/
),
status: 1,
write: [],
});
});
@@ -0,0 +1,15 @@
"use strict";
const path = require("path");
const prettier = require("prettier/local");
test("API resolveConfigFile", async () => {
const result = await prettier.resolveConfigFile();
expect(result).toEqual(path.join(__dirname, "../../.prettierrc"));
});
test("API resolveConfigFile.sync", () => {
const result = prettier.resolveConfigFile.sync();
expect(result).toEqual(path.join(__dirname, "../../.prettierrc"));
});
@@ -1,5 +1,6 @@
"use strict";
const { isCI } = require("ci-info");
const runPrettier = require("../runPrettier");
describe("format correctly if stdin content compatible with stdin-filepath", () => {
@@ -64,6 +65,56 @@ function f() {
});
});
describe("apply editorconfig for stdin-filepath with a deep path", () => {
runPrettier(
"cli",
["--stdin-filepath", "config/editorconfig/" + "a/".repeat(30) + "three.js"],
{
input: `
function f() {
console.log("should be indented with a tab");
}
`.trim(), // js
}
).test({
status: 0,
});
});
if (isCI) {
describe("apply editorconfig for stdin-filepath in root", () => {
const code = `
function f() {
console.log("should be indented with a tab");
}
`.trim();
runPrettier("cli", ["--stdin-filepath", "/foo.js"], {
input: code, // js
}).test({
status: 0,
stdout: code + "\n",
stderr: "",
write: [],
});
});
}
describe("apply editorconfig for stdin-filepath with a deep path", () => {
runPrettier(
"cli",
["--stdin-filepath", "config/editorconfig/" + "a/".repeat(30) + "three.js"],
{
input: `
function f() {
console.log("should be indented with a tab");
}
`.trim(), // js
}
).test({
status: 0,
});
});
describe("don’t apply editorconfig outside project for stdin-filepath with nonexistent directory", () => {
runPrettier(
"cli",
+5 -1
View File
@@ -2,7 +2,7 @@
const path = require("path");
const { thirdParty } = require("../env");
const { cosmiconfig, cosmiconfigSync } = require(thirdParty);
const { cosmiconfig, cosmiconfigSync, isCI } = require(thirdParty);
expect.addSnapshotSerializer(require("../path-serializer"));
@@ -62,3 +62,7 @@ describe("cosmiconfig", () => {
}).toThrowErrorMatchingSnapshot();
});
});
test("isCI", () => {
expect(typeof isCI()).toEqual("boolean");
});
@@ -0,0 +1 @@
1
@@ -0,0 +1,19 @@
{
"singleQuote": true,
"trailingComma": "all",
"overrides": [
{
"files": ["*.js"],
"options": {
"trailingComma": "es5"
}
},
{
"files": ["*.js"],
"excludeFiles": ["single-quote.js"],
"options": {
"singleQuote": false
}
}
]
}