diff --git a/src/common/util.js b/src/common/util.js index 5e21b0d0c..0004946fe 100644 --- a/src/common/util.js +++ b/src/common/util.js @@ -385,7 +385,7 @@ function addTrailingComment(node, comment) { } function isFrontMatterNode(node) { - return node && node.type === "front-matter"; + return node?.type === "front-matter"; } /** diff --git a/src/document/debug.js b/src/document/debug.js index dbc8937a8..2f52e2c21 100644 --- a/src/document/debug.js +++ b/src/document/debug.js @@ -80,9 +80,7 @@ function printDocToDebug(doc) { if (doc.type === DOC_TYPE_LINE) { const withBreakParent = - Array.isArray(parentParts) && - parentParts[index + 1] && - parentParts[index + 1].type === DOC_TYPE_BREAK_PARENT; + parentParts?.[index + 1]?.type === DOC_TYPE_BREAK_PARENT; if (doc.literal) { return withBreakParent ? "literalline" @@ -99,9 +97,7 @@ function printDocToDebug(doc) { if (doc.type === DOC_TYPE_BREAK_PARENT) { const afterHardline = - Array.isArray(parentParts) && - parentParts[index - 1] && - parentParts[index - 1].type === DOC_TYPE_LINE && + parentParts?.[index - 1]?.type === DOC_TYPE_LINE && parentParts[index - 1].hard; return afterHardline ? undefined : "breakParent"; } diff --git a/src/language-css/loc.js b/src/language-css/loc.js index 6a0caa94b..2407fd6d7 100644 --- a/src/language-css/loc.js +++ b/src/language-css/loc.js @@ -4,11 +4,7 @@ import lineColumnToIndex from "../utils/line-column-to-index.js"; function calculateLocStart(node, text) { // `postcss>=8` - if ( - node.source && - node.source.start && - typeof node.source.start.offset === "number" - ) { + if (typeof node.source?.start?.offset === "number") { return node.source.start.offset; } @@ -17,7 +13,7 @@ function calculateLocStart(node, text) { return node.sourceIndex; } - if (node.source && node.source.start) { + if (node.source?.start) { return lineColumnToIndex(node.source.start, text); } @@ -31,11 +27,7 @@ function calculateLocEnd(node, text) { } // `postcss>=8` - if ( - node.source && - node.source.end && - typeof node.source.end.offset === "number" - ) { + if (typeof node.source?.end?.offset === "number") { // https://github.com/postcss/postcss/issues/1450 return node.source.end.offset + 1; } @@ -106,11 +98,7 @@ function getValueRootOffset(node) { 1 + node.name.length + node.raws.afterName.match(/^\s*:?\s*/)[0].length; } - if ( - node.type !== "css-atrule" && - node.raws && - typeof node.raws.between === "string" - ) { + if (node.type !== "css-atrule" && typeof node.raws?.between === "string") { result += node.raws.between.length; } diff --git a/src/language-css/parser-postcss.js b/src/language-css/parser-postcss.js index 253a7f354..67cb2eec3 100644 --- a/src/language-css/parser-postcss.js +++ b/src/language-css/parser-postcss.js @@ -61,7 +61,7 @@ async function parseValueNode(valueNode, options) { } if (node.type === "func" && node.value === "url") { - const groups = (node.group && node.group.groups) || []; + const groups = node.group?.groups ?? []; // Create a view with any top-level comma groups flattened. let groupList = []; @@ -339,12 +339,7 @@ async function parseNestedCSS(node, options) { } catch { // noop } - if ( - ast && - ast.nodes && - ast.nodes.length === 1 && - ast.nodes[0].type === "css-rule" - ) { + if (ast?.nodes?.length === 1 && ast.nodes[0].type === "css-rule") { rules = ast.nodes[0].nodes; } } @@ -529,8 +524,7 @@ async function parseNestedCSS(node, options) { // `@color :blue;` if ( !["page", "nest", "keyframes"].includes(node.name) && - node.params && - node.params[0] === ":" + node.params?.[0] === ":" ) { node.variable = true; node.value = await parseValue(node.params.slice(1), options); diff --git a/src/language-css/printer-postcss.js b/src/language-css/printer-postcss.js index 9d1a73572..921d8436a 100644 --- a/src/language-css/printer-postcss.js +++ b/src/language-css/printer-postcss.js @@ -113,8 +113,7 @@ function genericPrint(path, options, print) { node.important ? " !important" : "", node.nodes ? [ - node.selector && - node.selector.type === "selector-unknown" && + node.selector?.type === "selector-unknown" && lastLineHasInlineComment(node.selector.value) ? line : node.selector @@ -236,8 +235,7 @@ function genericPrint(path, options, print) { } const isImportUnknownValueEndsWithSemiColon = node.name === "import" && - node.params && - node.params.type === "value-unknown" && + node.params?.type === "value-unknown" && node.params.value.endsWith(";"); return [ @@ -477,7 +475,7 @@ function genericPrint(path, options, print) { const ruleAncestorNode = getAncestorNode(path, "css-rule"); // Nested SCSS property - if (ruleAncestorNode && ruleAncestorNode.isSCSSNesterProperty) { + if (ruleAncestorNode?.isSCSSNesterProperty) { return adjustNumbers( adjustStrings(maybeToLowerCase(node.value), options) ); @@ -495,8 +493,7 @@ function genericPrint(path, options, print) { const grandParent = path.grandparent; if ( parentNode.type === "value-paren_group" && - grandParent && - grandParent.type === "value-func" && + grandParent?.type === "value-func" && grandParent.value === "selector" ) { const start = locEnd(parentNode.open) + 1; @@ -718,14 +715,14 @@ function genericPrint(path, options, print) { !hasEmptyRawBefore(iNextNode); const requireSpaceBeforeOperator = - (iNextNextNode && iNextNextNode.type === "value-func") || + iNextNextNode?.type === "value-func" || (iNextNextNode && isWordNode(iNextNextNode)) || iNode.type === "value-func" || isWordNode(iNode); const requireSpaceAfterOperator = iNextNode.type === "value-func" || isWordNode(iNextNode) || - (iPrevNode && iPrevNode.type === "value-func") || + iPrevNode?.type === "value-func" || (iPrevNode && isWordNode(iPrevNode)); // Formatting `/`, `+`, `-` sign @@ -806,7 +803,7 @@ function genericPrint(path, options, print) { continue; } // allow function(returns-list($list)...) - if (iNextNode && iNextNode.value === "...") { + if (iNextNode?.value === "...") { continue; } @@ -897,7 +894,7 @@ function genericPrint(path, options, print) { const isSCSSMapItem = isSCSSMapItemNode(path, options); const lastItem = node.groups.at(-1); - const isLastItemComment = lastItem && lastItem.type === "value-comment"; + const isLastItemComment = lastItem?.type === "value-comment"; const isKey = isKeyInValuePairNode(node, parentNode); const isConfiguration = isConfigurationNode(node, parentNode); const isVarFunction = isVarFunctionNode(parentNode); @@ -933,8 +930,7 @@ function genericPrint(path, options, print) { child.type === "value-comma_group" && child.groups && child.groups[0].type !== "value-paren_group" && - child.groups[2] && - child.groups[2].type === "value-paren_group" + child.groups[2]?.type === "value-paren_group" ) { const parts = getDocParts(printed[0].contents.contents); parts[1] = group(parts[1]); @@ -1010,8 +1006,7 @@ function genericPrint(path, options, print) { return [ node.value, // Don't add spaces on escaped colon `:`, e.g: grid-template-rows: [row-1-00\:00] auto; - (prevNode && - typeof prevNode.value === "string" && + (typeof prevNode?.value === "string" && prevNode.value.endsWith("\\")) || // Don't add spaces on `:` in `url` function (i.e. `url(fbglyph: cross-outline, fig-white)`) insideValueFunctionNode(path, "url") @@ -1046,8 +1041,7 @@ function printNodeSequence(path, options, print) { path.each((pathChild, i, nodes) => { const prevNode = nodes[i - 1]; if ( - prevNode && - prevNode.type === "css-comment" && + prevNode?.type === "css-comment" && prevNode.text.trim() === "prettier-ignore" ) { const childNode = pathChild.getValue(); diff --git a/src/language-css/utils/index.js b/src/language-css/utils/index.js index 00c23d72f..70b1ea60a 100644 --- a/src/language-css/utils/index.js +++ b/src/language-css/utils/index.js @@ -44,8 +44,7 @@ function isWideKeywords(value) { function isKeyframeAtRuleKeywords(path, value) { const atRuleAncestorNode = getAncestorNode(path, "css-atrule"); return ( - atRuleAncestorNode?.name && - atRuleAncestorNode.name.toLowerCase().endsWith("keyframes") && + atRuleAncestorNode?.name?.toLowerCase().endsWith("keyframes") && ["from", "to"].includes(value.toLowerCase()) ); } diff --git a/src/language-handlebars/printer-glimmer.js b/src/language-handlebars/printer-glimmer.js index 7b48b170e..74eca053e 100644 --- a/src/language-handlebars/printer-glimmer.js +++ b/src/language-handlebars/printer-glimmer.js @@ -453,13 +453,13 @@ function printStartingTagEndMarker(node) { function printOpeningMustache(node) { const mustache = node.escaped === false ? "{{{" : "{{"; - const strip = node.strip && node.strip.open ? "~" : ""; + const strip = node.strip?.open ? "~" : ""; return [mustache, strip]; } function printClosingMustache(node) { const mustache = node.escaped === false ? "}}}" : "}}"; - const strip = node.strip && node.strip.close ? "~" : ""; + const strip = node.strip?.close ? "~" : ""; return [strip, mustache]; } @@ -649,7 +649,7 @@ function splitByHtmlWhitespace(string) { function getCurrentAttributeName(path) { for (let depth = 0; depth < 2; depth++) { const parentNode = path.getParentNode(depth); - if (parentNode && parentNode.type === "AttrNode") { + if (parentNode?.type === "AttrNode") { return parentNode.name.toLowerCase(); } } diff --git a/src/language-html/parser-html.js b/src/language-html/parser-html.js index d55db9b38..196908374 100644 --- a/src/language-html/parser-html.js +++ b/src/language-html/parser-html.js @@ -87,11 +87,8 @@ function ngHtmlParser( if (node.type !== "element" || node.name !== "template") { return false; } - const langAttr = node.attrs.find((attr) => attr.name === "lang"); - const langValue = langAttr && langAttr.value; - return ( - !langValue || inferParserByLanguage(langValue, options) === "html" - ); + const language = node.attrs.find((attr) => attr.name === "lang")?.value; + return !language || inferParserByLanguage(language, options) === "html"; }; if (rootNodes.some(shouldParseAsHTML)) { /** @type {ParserTreeResult | undefined} */ diff --git a/src/language-html/print-preprocess.js b/src/language-html/print-preprocess.js index 15ba2fe8e..7c66b1dc9 100644 --- a/src/language-html/print-preprocess.js +++ b/src/language-html/print-preprocess.js @@ -61,11 +61,9 @@ function mergeIfConditionalStartEndCommentIntoElementOpeningTag( */ const isTarget = (node) => node.type === "element" && - node.prev && - node.prev.type === "ieConditionalStartComment" && + node.prev?.type === "ieConditionalStartComment" && node.prev.sourceSpan.end.offset === node.startSourceSpan.start.offset && - node.firstChild && - node.firstChild.type === "ieConditionalEndComment" && + node.firstChild?.type === "ieConditionalEndComment" && node.firstChild.sourceSpan.start.offset === node.startSourceSpan.end.offset; ast.walk((node) => { if (node.children) { @@ -154,10 +152,8 @@ function mergeSimpleElementIntoText(ast /*, options */) { !node.hasLeadingSpaces && node.isTrailingSpaceSensitive && !node.hasTrailingSpaces && - node.prev && - node.prev.type === "text" && - node.next && - node.next.type === "text"; + node.prev?.type === "text" && + node.next?.type === "text"; ast.walk((node) => { if (node.children) { for (let i = 0; i < node.children.length; i++) { diff --git a/src/language-html/print/tag.js b/src/language-html/print/tag.js index def69b776..569020b64 100644 --- a/src/language-html/print/tag.js +++ b/src/language-html/print/tag.js @@ -143,8 +143,7 @@ function needsToBorrowLastChildClosingTagEndMarker(node) { * > */ return ( - node.lastChild && - node.lastChild.isTrailingSpaceSensitive && + node.lastChild?.isTrailingSpaceSensitive && !node.lastChild.hasTrailingSpaces && !isTextLikeNode(getLastDescendant(node.lastChild)) && !isPreLikeNode(node) @@ -227,8 +226,7 @@ function printAttributes(path, options, print) { } const ignoreAttributeData = - node.prev && - node.prev.type === "comment" && + node.prev?.type === "comment" && getPrettierIgnoreAttributeCommentData(node.prev.value); const hasPrettierIgnoreAttribute = diff --git a/src/language-html/utils/index.js b/src/language-html/utils/index.js index 690d731db..9eeb978d7 100644 --- a/src/language-html/utils/index.js +++ b/src/language-html/utils/index.js @@ -136,9 +136,7 @@ function isLeadingSpaceSensitiveNode(node, options) { if ( isLeadingSpaceSensitive && !node.prev && - node.parent && - node.parent.tagDefinition && - node.parent.tagDefinition.ignoreFirstLf + node.parent?.tagDefinition?.ignoreFirstLf ) { return node.type === "interpolation"; } @@ -331,7 +329,7 @@ function getLastDescendant(node) { } function hasNonTextChild(node) { - return node.children && node.children.some((child) => child.type !== "text"); + return node.children?.some((child) => child.type !== "text"); } function _inferScriptParser(node) { @@ -480,7 +478,7 @@ function hasParent(node, fn) { } function getNodeCssStyleDisplay(node, options) { - if (node.prev && node.prev.type === "comment") { + if (node.prev?.type === "comment") { // const match = node.prev.value.match(/^\s*display:\s*([a-z]+)\s*$/); if (match) { @@ -504,11 +502,7 @@ function getNodeCssStyleDisplay(node, options) { return "block"; default: // See https://github.com/prettier/prettier/issues/8151 - if ( - options.parser === "vue" && - node.parent && - node.parent.type === "root" - ) { + if (options.parser === "vue" && node.parent?.type === "root") { return "block"; } return ( diff --git a/src/language-js/clean.js b/src/language-js/clean.js index a4186cab6..7dd01199d 100644 --- a/src/language-js/clean.js +++ b/src/language-js/clean.js @@ -119,8 +119,7 @@ function clean(ast, newObj, parent) { // We change quotes if ( ast.type === "JSXAttribute" && - ast.value && - ast.value.type === "Literal" && + ast.value?.type === "Literal" && /["']|"|'/.test(ast.value.value) ) { newObj.value.value = newObj.value.value.replace(/["']|"|'/g, '"'); diff --git a/src/language-js/comments/handle-comments.js b/src/language-js/comments/handle-comments.js index 161e78f1a..b3586597c 100644 --- a/src/language-js/comments/handle-comments.js +++ b/src/language-js/comments/handle-comments.js @@ -391,7 +391,7 @@ function handleClassComments({ if (classLikeNodeTypes.has(enclosingNode?.type)) { if ( isNonEmptyArray(enclosingNode.decorators) && - !(followingNode && followingNode.type === "Decorator") + !(followingNode?.type === "Decorator") ) { addTrailingComment(enclosingNode.decorators.at(-1), comment); return true; @@ -699,7 +699,7 @@ function handleOnlyComments({ isLastComment, }) { // With Flow the enclosingNode is undefined so use the AST instead. - if (ast && ast.body && ast.body.length === 0) { + if (ast?.body?.length === 0) { if (isLastComment) { addDanglingComment(ast, comment); } else { @@ -710,7 +710,7 @@ function handleOnlyComments({ if ( enclosingNode?.type === "Program" && - enclosingNode?.body.length === 0 && + enclosingNode.body.length === 0 && !isNonEmptyArray(enclosingNode.directives) ) { if (isLastComment) { @@ -723,7 +723,7 @@ function handleOnlyComments({ if ( followingNode?.type === "Program" && - followingNode?.body.length === 0 && + followingNode.body.length === 0 && enclosingNode?.type === "ModuleExpression" ) { addDanglingComment(followingNode, comment); diff --git a/src/language-js/comments/printer-methods.js b/src/language-js/comments/printer-methods.js index 9686fb99e..846632e55 100644 --- a/src/language-js/comments/printer-methods.js +++ b/src/language-js/comments/printer-methods.js @@ -46,8 +46,7 @@ function getCommentChildNodes(node, options) { options.parser === "meriyah" || options.parser === "__babel_estree") && node.type === "MethodDefinition" && - node.value && - node.value.type === "FunctionExpression" && + node.value?.type === "FunctionExpression" && getFunctionParameters(node.value).length === 0 && !node.value.returnType && !isNonEmptyArray(node.value.typeParameters) && @@ -67,7 +66,7 @@ function hasPrettierIgnore(path) { */ function willPrintOwnComments({ node, parent }) { return ( - ((node && isJsxNode(node)) || + (isJsxNode(node) || (parent && (parent.type === "JSXSpreadAttribute" || parent.type === "JSXSpreadChild" || diff --git a/src/language-js/embed.js b/src/language-js/embed.js index be8892041..b39e46781 100644 --- a/src/language-js/embed.js +++ b/src/language-js/embed.js @@ -69,8 +69,7 @@ function getEmbedder(path) { */ function isMarkdown({ node, parent }) { return ( - parent && - parent.type === "TaggedTemplateExpression" && + parent?.type === "TaggedTemplateExpression" && node.quasis.length === 1 && parent.tag.type === "Identifier" && (parent.tag.name === "md" || parent.tag.name === "markdown") @@ -94,12 +93,10 @@ function isStyledJsx({ node, parent, grandparent }) { grandparent.openingElement.attributes.some( (attribute) => attribute.name.name === "jsx" )) || - (parent && - parent.type === "TaggedTemplateExpression" && + (parent?.type === "TaggedTemplateExpression" && parent.tag.type === "Identifier" && parent.tag.name === "css") || - (parent && - parent.type === "TaggedTemplateExpression" && + (parent?.type === "TaggedTemplateExpression" && parent.tag.type === "MemberExpression" && parent.tag.object.name === "css" && (parent.tag.property.name === "global" || @@ -205,9 +202,8 @@ function isStyledComponents({ parent }) { */ function isCssProp({ parent, grandparent }) { return ( - grandparent && + grandparent?.type === "JSXAttribute" && parent.type === "JSXExpressionContainer" && - grandparent.type === "JSXAttribute" && grandparent.name.type === "JSXIdentifier" && grandparent.name.name === "css" ); diff --git a/src/language-js/needs-parens.js b/src/language-js/needs-parens.js index e293ff3c4..2d9c221c5 100644 --- a/src/language-js/needs-parens.js +++ b/src/language-js/needs-parens.js @@ -44,8 +44,7 @@ function needsParens(path, options) { // If the inner JS formatter removes the parens, the expression might change its meaning: // f((a + b) / 2) vs f(a + b / 2) if ( - node.extra && - node.extra.parenthesized && + node.extra?.parenthesized && /^PRETTIER_HTML_PLACEHOLDER_\d+_\d+_IN_JS$/.test(node.name) ) { return true; @@ -215,7 +214,7 @@ function needsParens(path, options) { if (node.operator === "in" && isPathInForStatementInitializer(path)) { return true; } - if (node.operator === "|>" && node.extra && node.extra.parenthesized) { + if (node.operator === "|>" && node.extra?.parenthesized) { const grandParent = path.grandparent; if ( grandParent.type === "BinaryExpression" && @@ -485,9 +484,7 @@ function needsParens(path, options) { (parent.type === "FunctionTypeParam" && parent.name === null && getFunctionParameters(node).some( - (param) => - param.typeAnnotation && - param.typeAnnotation.type === "NullableTypeAnnotation" + (param) => param.typeAnnotation?.type === "NullableTypeAnnotation" )) ); } @@ -562,7 +559,6 @@ function needsParens(path, options) { if ( parent.type === "SequenceExpression" && - grandParent && grandParent.type === "ForStatement" && (grandParent.init === parent || grandParent.update === parent) ) { @@ -572,7 +568,6 @@ function needsParens(path, options) { if ( key === "value" && parent.type === "Property" && - grandParent && grandParent.type === "ObjectPattern" && grandParent.properties.includes(parent) ) { @@ -637,9 +632,7 @@ function needsParens(path, options) { case "ArrowFunctionExpression": switch (parent.type) { case "BinaryExpression": - return ( - parent.operator !== "|>" || (node.extra && node.extra.parenthesized) - ); + return parent.operator !== "|>" || node.extra?.parenthesized; case "NewExpression": case "CallExpression": case "OptionalCallExpression": @@ -742,7 +735,7 @@ function needsParens(path, options) { parent.type === "NGMicrosyntaxExpression" || (parent.type === "ObjectProperty" && // Preserve parens for compatibility with AngularJS expressions - !(node.extra && node.extra.parenthesized)) || + !node.extra?.parenthesized) || parent.type === "ArrayExpression" || (key === "arguments" && isCallExpression(parent)) || (key === "right" && parent.type === "NGPipeExpression") || @@ -849,7 +842,7 @@ function isPathInForStatementInitializer(path) { let { node } = path; while (node) { const parent = path.getParentNode(i++); - if (parent && parent.type === "ForStatement" && parent.init === node) { + if (parent?.type === "ForStatement" && parent.init === node) { return true; } node = parent; diff --git a/src/language-js/parse/babel.js b/src/language-js/parse/babel.js index 85a6da093..4e232ba21 100644 --- a/src/language-js/parse/babel.js +++ b/src/language-js/parse/babel.js @@ -66,7 +66,7 @@ const appendPlugins = (plugins, options = parseOptions) => ({ // https://github.com/babel/babel/pull/7934/files#diff-a739835084910b0ee3ea649df5a4d223R67 const FLOW_PRAGMA_REGEX = /@(?:no)?flow\b/; function isFlowFile(text, options) { - if (options.filepath && options.filepath.endsWith(".js.flow")) { + if (options.filepath?.endsWith(".js.flow")) { return true; } diff --git a/src/language-js/parse/postprocess/index.js b/src/language-js/parse/postprocess/index.js index 8ac920460..c4e421d6b 100644 --- a/src/language-js/parse/postprocess/index.js +++ b/src/language-js/parse/postprocess/index.js @@ -32,10 +32,7 @@ function postprocess(ast, options) { // Let's use the fact that those ancestors and ParenthesizedExpression have the same start offset. ast = visitNode(ast, (node) => { - if ( - node.leadingComments && - node.leadingComments.some(isTypeCastComment) - ) { + if (node.leadingComments?.some(isTypeCastComment)) { startOffsetsOfTypeCastedNodes.add(locStart(node)); } }); @@ -75,7 +72,7 @@ function postprocess(ast, options) { // fix unexpected locEnd caused by --no-semi style case "VariableDeclaration": { const lastDeclaration = node.declarations.at(-1); - if (lastDeclaration && lastDeclaration.init) { + if (lastDeclaration?.init) { overrideLocEnd(node, lastDeclaration); } break; @@ -133,11 +130,7 @@ function postprocess(ast, options) { // TODO: Remove this when https://github.com/meriyah/meriyah/issues/200 get fixed case "ExportAllDeclaration": { const { exported } = node; - if ( - options.parser === "meriyah" && - exported && - exported.type === "Identifier" - ) { + if (options.parser === "meriyah" && exported?.type === "Identifier") { const raw = options.originalText.slice( locStart(exported), locEnd(exported) diff --git a/src/language-js/print/array.js b/src/language-js/print/array.js index 31485ba48..6db1e89eb 100644 --- a/src/language-js/print/array.js +++ b/src/language-js/print/array.js @@ -47,7 +47,7 @@ function printArray(path, options, print) { parts.push(printEmptyArray(path, openBracket, closeBracket, options)); } else { const lastElem = node.elements.at(-1); - const canHaveTrailingComma = !(lastElem && lastElem.type === "RestElement"); + const canHaveTrailingComma = lastElem?.type !== "RestElement"; // JavaScript allows you to have empty elements in an array which // changes its length based on the number of commas. The algorithm diff --git a/src/language-js/print/assignment.js b/src/language-js/print/assignment.js index 47cd80733..6180f6701 100644 --- a/src/language-js/print/assignment.js +++ b/src/language-js/print/assignment.js @@ -237,8 +237,7 @@ function isComplexDestructuring(node) { leftNode.properties.some( (property) => isObjectProperty(property) && - (!property.shorthand || - (property.value && property.value.type === "AssignmentPattern")) + (!property.shorthand || property.value?.type === "AssignmentPattern") ) ); } @@ -269,7 +268,7 @@ function isComplexTypeAliasParams(node) { } function getTypeParametersFromTypeAlias(node) { - if (isTypeAlias(node) && node.typeParameters && node.typeParameters.params) { + if (isTypeAlias(node) && node.typeParameters?.params) { return node.typeParameters.params; } return null; @@ -304,17 +303,12 @@ function hasComplexTypeAnnotation(node) { function isArrowFunctionVariableDeclarator(node) { return ( node.type === "VariableDeclarator" && - node.init && - node.init.type === "ArrowFunctionExpression" + node.init?.type === "ArrowFunctionExpression" ); } function getTypeParametersFromTypeReference(node) { - if ( - isTypeReference(node) && - node.typeParameters && - node.typeParameters.params - ) { + if (isTypeReference(node) && node.typeParameters?.params) { return node.typeParameters.params; } return null; @@ -463,10 +457,7 @@ function isCallExpressionWithComplexTypeArguments(node, print) { } function getTypeArgumentsFromCallExpression(node) { - return ( - (node.typeParameters && node.typeParameters.params) || - (node.typeArguments && node.typeArguments.params) - ); + return (node.typeParameters ?? node.typeArguments)?.params; } export { diff --git a/src/language-js/print/class.js b/src/language-js/print/class.js index b5a99afbd..41d2ae2b5 100644 --- a/src/language-js/print/class.js +++ b/src/language-js/print/class.js @@ -38,10 +38,9 @@ function printClass(path, options, print) { // Keep old behaviour of extends in same line // If there is only on extends and there are not comments const groupMode = - (node.id && hasComment(node.id, CommentCheckFlags.Trailing)) || - (node.typeParameters && - hasComment(node.typeParameters, CommentCheckFlags.Trailing)) || - (node.superClass && hasComment(node.superClass)) || + hasComment(node.id, CommentCheckFlags.Trailing) || + hasComment(node.typeParameters, CommentCheckFlags.Trailing) || + hasComment(node.superClass) || isNonEmptyArray(node.extends) || // DeclareClass isNonEmptyArray(node.mixins) || isNonEmptyArray(node.implements); diff --git a/src/language-js/print/decorators.js b/src/language-js/print/decorators.js index 7af08071b..22a446a65 100644 --- a/src/language-js/print/decorators.js +++ b/src/language-js/print/decorators.js @@ -6,7 +6,7 @@ import { breakParent, group, } from "../../document/builders.js"; -import { locStart, locEnd } from "../loc.js"; +import { locEnd, hasSameLocStart } from "../loc.js"; import { getParentExportDeclaration } from "../utils/index.js"; function printClassMemberDecorators(path, options, print) { @@ -71,11 +71,9 @@ function hasDecoratorsBeforeExport(node) { return false; } - const decorators = node.declaration && node.declaration.decorators; + const decorators = node.declaration?.decorators; - return ( - isNonEmptyArray(decorators) && locStart(node) === locStart(decorators[0]) - ); + return isNonEmptyArray(decorators) && hasSameLocStart(node, decorators[0]); } export { diff --git a/src/language-js/print/function.js b/src/language-js/print/function.js index 72752d8e9..75bb53720 100644 --- a/src/language-js/print/function.js +++ b/src/language-js/print/function.js @@ -192,7 +192,7 @@ function printArrowFunctionSignature(path, options, print, args) { if (shouldPrintParamsWithoutParens(path, options)) { parts.push(print(["params", 0])); } else { - const expandArg = args && (args.expandLastArg || args.expandFirstArg); + const expandArg = args?.expandLastArg || args?.expandFirstArg; let returnTypeDoc = printReturnType(path, print); if (expandArg) { if (willBreak(returnTypeDoc)) { @@ -247,14 +247,14 @@ function printArrowChain( const name = path.getName(); const { parent } = path; const isCallee = isCallLikeExpression(parent) && name === "callee"; - const isAssignmentRhs = Boolean(args && args.assignmentLayout); + const isAssignmentRhs = Boolean(args?.assignmentLayout); const shouldPutBodyOnSeparateLine = tailNode.body.type !== "BlockStatement" && tailNode.body.type !== "ObjectExpression" && tailNode.body.type !== "SequenceExpression"; const shouldBreakBeforeChain = (isCallee && shouldPutBodyOnSeparateLine) || - (args && args.assignmentLayout === "chain-tail-arrow-chain"); + args?.assignmentLayout === "chain-tail-arrow-chain"; const groupId = Symbol("arrow-chain"); @@ -429,7 +429,7 @@ function printReturnType(path, print) { const parts = [returnType]; // prepend colon to TypeScript type annotation - if (node.returnType && node.returnType.typeAnnotation) { + if (node.returnType?.typeAnnotation) { parts.unshift(": "); } diff --git a/src/language-js/print/interface.js b/src/language-js/print/interface.js index ad8583b57..12af9c2df 100644 --- a/src/language-js/print/interface.js +++ b/src/language-js/print/interface.js @@ -49,7 +49,7 @@ function printInterface(path, options, print) { } if ( - (node.id && hasComment(node.id, CommentCheckFlags.Trailing)) || + hasComment(node.id, CommentCheckFlags.Trailing) || isNonEmptyArray(node.extends) ) { if (shouldIndentOnlyHeritageClauses) { diff --git a/src/language-js/print/jsx.js b/src/language-js/print/jsx.js index d4f84afe3..5072098f7 100644 --- a/src/language-js/print/jsx.js +++ b/src/language-js/print/jsx.js @@ -113,10 +113,7 @@ function printJsxElementInternal(path, options, print) { ? " " : ifBreak([rawJsxWhitespace, softline], " "); - const isFacebookTranslationTag = - node.openingElement && - node.openingElement.name && - node.openingElement.name.name === "fbt"; + const isFacebookTranslationTag = node.openingElement?.name?.name === "fbt"; const children = printJsxChildren( path, @@ -393,7 +390,7 @@ function separatorNoWhitespace( if ( (childNode.type === "JSXElement" && !childNode.closingElement) || - (nextNode && nextNode.type === "JSXElement" && !nextNode.closingElement) + (nextNode?.type === "JSXElement" && !nextNode.closingElement) ) { return child.length === 1 ? softline : hardline; } @@ -413,7 +410,7 @@ function separatorWithWhitespace( if (child.length === 1) { return (childNode.type === "JSXElement" && !childNode.closingElement) || - (nextNode && nextNode.type === "JSXElement" && !nextNode.closingElement) + (nextNode?.type === "JSXElement" && !nextNode.closingElement) ? hardline : softline; } @@ -531,8 +528,7 @@ function printJsxOpeningElement(path, options, print) { const { node } = path; const nameHasComments = - (node.name && hasComment(node.name)) || - (node.typeParameters && hasComment(node.typeParameters)); + hasComment(node.name) || hasComment(node.typeParameters); // Don't break self-closing elements with no attributes and no comments if (node.selfClosing && node.attributes.length === 0 && !nameHasComments) { @@ -541,8 +537,7 @@ function printJsxOpeningElement(path, options, print) { // don't break up opening elements with a single long text attribute if ( - node.attributes && - node.attributes.length === 1 && + node.attributes?.length === 1 && node.attributes[0].value && isStringLiteral(node.attributes[0].value) && !node.attributes[0].value.value.includes("\n") && @@ -570,14 +565,12 @@ function printJsxOpeningElement(path, options, print) { // We should print the opening element expanded if any prop value is a // string literal with newlines - const shouldBreak = - node.attributes && - node.attributes.some( - (attr) => - attr.value && - isStringLiteral(attr.value) && - attr.value.value.includes("\n") - ); + const shouldBreak = node.attributes?.some( + (attr) => + attr.value && + isStringLiteral(attr.value) && + attr.value.value.includes("\n") + ); const attributeLine = options.singleAttributePerLine && node.attributes.length > 1 diff --git a/src/language-js/print/member-chain.js b/src/language-js/print/member-chain.js index 450b88fc7..23610e0e9 100644 --- a/src/language-js/print/member-chain.js +++ b/src/language-js/print/member-chain.js @@ -272,7 +272,7 @@ function printMemberChain(path, options, print) { } function shouldNotWrap(groups) { - const hasComputed = groups[1].length > 0 && groups[1][0].node.computed; + const hasComputed = groups[1][0]?.node.computed; if (groups[0].length === 1) { const firstNode = groups[0][0].node; diff --git a/src/language-js/print/misc.js b/src/language-js/print/misc.js index 290d69205..cd6cfaf39 100644 --- a/src/language-js/print/misc.js +++ b/src/language-js/print/misc.js @@ -43,15 +43,13 @@ function printFunctionTypeParameters(path, options, print) { } function printTypeAnnotation(path, options, print) { - const { node } = path; + const { node, parent, key } = path; if (!node.typeAnnotation) { return ""; } - const parentNode = path.parent; - const isFunctionDeclarationIdentifier = - parentNode.type === "DeclareFunction" && parentNode.id === node; + parent.type === "DeclareFunction" && key === "id"; return [isFunctionDeclarationIdentifier ? "" : ": ", print("typeAnnotation")]; } diff --git a/src/language-js/print/statement.js b/src/language-js/print/statement.js index 3cd9b694a..275abaf50 100644 --- a/src/language-js/print/statement.js +++ b/src/language-js/print/statement.js @@ -168,7 +168,7 @@ const isClassProperty = ({ type }) => * @returns {boolean} */ function shouldPrintSemicolonAfterClassProperty(node, nextNode) { - const name = node.key && node.key.name; + const name = node.key?.name; // this isn't actually possible yet with most parsers available today // so isn't properly tested yet. if ( @@ -191,7 +191,7 @@ function shouldPrintSemicolonAfterClassProperty(node, nextNode) { } if (!nextNode.computed) { - const name = nextNode.key && nextNode.key.name; + const name = nextNode.key?.name; if (name === "in" || name === "instanceof") { return true; } diff --git a/src/language-js/print/type-annotation.js b/src/language-js/print/type-annotation.js index 52e366604..4ec80268a 100644 --- a/src/language-js/print/type-annotation.js +++ b/src/language-js/print/type-annotation.js @@ -220,7 +220,7 @@ function printFunctionType(path, options, print) { !parent.optional && locStart(parent) === locStart(node)) || parent.type === "ObjectTypeCallProperty" || - (parentParentParent && parentParentParent.type === "DeclareFunction") + parentParentParent?.type === "DeclareFunction" ); let needsColon = diff --git a/src/language-js/print/typescript.js b/src/language-js/print/typescript.js index 36af1c8f0..dadbc8665 100644 --- a/src/language-js/print/typescript.js +++ b/src/language-js/print/typescript.js @@ -437,8 +437,7 @@ function printTypescript(path, options, print) { const { parent } = path; const isExternalModule = isLiteral(node.id); const parentIsDeclaration = parent.type === "TSModuleDeclaration"; - const bodyIsDeclaration = - node.body && node.body.type === "TSModuleDeclaration"; + const bodyIsDeclaration = node.body?.type === "TSModuleDeclaration"; if (parentIsDeclaration) { parts.push("."); diff --git a/src/language-js/utils/index.js b/src/language-js/utils/index.js index 0460c0ae9..c81646aba 100644 --- a/src/language-js/utils/index.js +++ b/src/language-js/utils/index.js @@ -1112,8 +1112,7 @@ function isPrettierIgnoreComment(comment) { function hasNodeIgnoreComment(node) { return ( - node && - (node.prettierIgnore || hasComment(node, CommentCheckFlags.PrettierIgnore)) + node?.prettierIgnore || hasComment(node, CommentCheckFlags.PrettierIgnore) ); } diff --git a/src/language-json/printer-estree-json.js b/src/language-json/printer-estree-json.js index c507dfd3b..4611b8f45 100644 --- a/src/language-json/printer-estree-json.js +++ b/src/language-json/printer-estree-json.js @@ -49,8 +49,8 @@ function genericPrint(path, options, print) { case "NumericLiteral": return JSON.stringify(node.value); case "Identifier": { - const { parent } = path; - if (parent && parent.type === "ObjectProperty" && parent.key === node) { + const { parent, key } = path; + if (parent.type === "ObjectProperty" && key === "key") { return JSON.stringify(node.name); } return node.name; diff --git a/src/language-markdown/clean.js b/src/language-markdown/clean.js index 6c1dc4706..39970befd 100644 --- a/src/language-markdown/clean.js +++ b/src/language-markdown/clean.js @@ -58,8 +58,7 @@ function clean(ast, newObj, parent) { // for insert pragma if ( - parent && - parent.type === "root" && + parent?.type === "root" && parent.children.length > 0 && (parent.children[0] === ast || (isFrontMatterNode(parent.children[0]) && parent.children[1] === ast)) && diff --git a/src/language-markdown/printer-markdown.js b/src/language-markdown/printer-markdown.js index 42e934fe8..1a3c81c22 100644 --- a/src/language-markdown/printer-markdown.js +++ b/src/language-markdown/printer-markdown.js @@ -261,11 +261,9 @@ function genericPrint(path, options, print) { ]; } case "html": { - const { parent } = path; + const { parent, isLast } = path; const value = - parent.type === "root" && parent.children.at(-1) === node - ? node.value.trimEnd() - : node.value; + parent.type === "root" && isLast ? node.value.trimEnd() : node.value; const isHtmlComment = /^$/s.test(value); return replaceEndOfLine( @@ -742,7 +740,7 @@ function shouldPrePrintHardline(node, data) { } function shouldPrePrintDoubleHardline(node, data) { - const isSequence = (data.prevNode && data.prevNode.type) === node.type; + const isSequence = data.prevNode?.type === node.type; const isSiblingNode = isSequence && SIBLING_NODE_TYPES.has(node.type); const isInTightListItem = diff --git a/src/language-yaml/print/flow-mapping-sequence.js b/src/language-yaml/print/flow-mapping-sequence.js index 3c158689b..591f85b59 100644 --- a/src/language-yaml/print/flow-mapping-sequence.js +++ b/src/language-yaml/print/flow-mapping-sequence.js @@ -21,8 +21,7 @@ function printFlowMapping(path, print, options) { } const lastItem = node.children.at(-1); const isLastItemEmptyMappingItem = - lastItem && - lastItem.type === "flowMappingItem" && + lastItem?.type === "flowMappingItem" && isEmptyNode(lastItem.key) && isEmptyNode(lastItem.value); diff --git a/src/language-yaml/print/mapping-item.js b/src/language-yaml/print/mapping-item.js index 191e30ad0..687a0aac5 100644 --- a/src/language-yaml/print/mapping-item.js +++ b/src/language-yaml/print/mapping-item.js @@ -185,7 +185,7 @@ function isAbsolutelyPrintedAsSingleLineNode(node, options) { } function needsSpaceInFrontOfMappingValue(node) { - return node.key.content && node.key.content.type === "alias"; + return node.key.content?.type === "alias"; } function isSingleLineNode(node) { diff --git a/src/language-yaml/utils.js b/src/language-yaml/utils.js index a6147c44b..cc417de71 100644 --- a/src/language-yaml/utils.js +++ b/src/language-yaml/utils.js @@ -18,9 +18,7 @@ function getAncestorCount(path, filter) { */ function isNode(value, types) { return ( - value && - typeof value.type === "string" && - (!types || types.includes(value.type)) + typeof value?.type === "string" && (!types || types.includes(value.type)) ); } diff --git a/src/main/comments.js b/src/main/comments.js index 94dddbc2e..de599e9c2 100644 --- a/src/main/comments.js +++ b/src/main/comments.js @@ -118,7 +118,7 @@ function decorateComment(node, comment, options, enclosingNode) { // We don't want comments inside of different expressions inside of the same // template literal to move to another expression. - if (enclosingNode && enclosingNode.type === "TemplateLiteral") { + if (enclosingNode?.type === "TemplateLiteral") { const { quasis } = enclosingNode; const commentIndex = findExpressionIndexForComment( quasis, @@ -427,7 +427,7 @@ function printLeadingComment(path, options) { const parts = [printComment(path, options)]; const { printer, originalText, locStart, locEnd } = options; - const isBlock = printer.isBlockComment && printer.isBlockComment(comment); + const isBlock = printer.isBlockComment?.(comment); // Leading block comments should see if they need to stay on the // same line or not. @@ -551,7 +551,7 @@ function printCommentsSeparately(path, options, ignored) { let printedTrailingComment; path.each(() => { const comment = path.node; - if (ignored && ignored.has(comment)) { + if (ignored?.has(comment)) { return; } diff --git a/src/main/core.js b/src/main/core.js index 642b87959..794ab6ec1 100644 --- a/src/main/core.js +++ b/src/main/core.js @@ -41,7 +41,7 @@ async function coreFormat(originalText, opts, addAlignmentSize = 0) { if (opts.cursorOffset >= 0) { const nodeResult = findNodeAtOffset(ast, opts.cursorOffset, opts); - if (nodeResult && nodeResult.node) { + if (nodeResult?.node) { opts.cursorNode = nodeResult.node; } } diff --git a/src/main/options-normalizer.js b/src/main/options-normalizer.js index 33d601701..820e412b2 100644 --- a/src/main/options-normalizer.js +++ b/src/main/options-normalizer.js @@ -160,7 +160,7 @@ function optionInfoToSchema(optionInfo, { isCLI, optionInfos, FlagSchema }) { case "choice": SchemaConstructor = vnopts.ChoiceSchema; parameters.choices = optionInfo.choices.map((choiceInfo) => - typeof choiceInfo === "object" && choiceInfo.redirect + choiceInfo?.redirect ? { ...choiceInfo, redirect: { diff --git a/src/main/options.js b/src/main/options.js index cf25122cd..9d900d6ae 100644 --- a/src/main/options.js +++ b/src/main/options.js @@ -67,9 +67,7 @@ async function normalize(options, opts = {}) { const pluginDefaults = Object.fromEntries( supportOptions .filter( - (optionInfo) => - optionInfo.pluginDefaults && - optionInfo.pluginDefaults[plugin.name] !== undefined + (optionInfo) => optionInfo.pluginDefaults?.[plugin.name] !== undefined ) .map((optionInfo) => [ optionInfo.name, @@ -104,7 +102,7 @@ function getPlugin(options) { throw new Error("getPlugin() requires astFormat to be set"); } const printerPlugin = options.plugins.find( - (plugin) => plugin.printers && plugin.printers[astFormat] + (plugin) => plugin.printers?.[astFormat] ); // TODO: test this with plugins /* c8 ignore next 3 */ @@ -124,12 +122,8 @@ function inferParser(filepath, plugins) { // do it last. let language = languages.find( (language) => - (language.extensions && - language.extensions.some((extension) => - filename.endsWith(extension) - )) || - (language.filenames && - language.filenames.some((name) => name.toLowerCase() === filename)) + language.extensions?.some((extension) => filename.endsWith(extension)) || + language.filenames?.some((name) => name.toLowerCase() === filename) ); if ( @@ -138,13 +132,14 @@ function inferParser(filepath, plugins) { !filename.includes(".") ) { const interpreter = getInterpreter(filepath); - language = languages.find( - (language) => - language.interpreters && language.interpreters.includes(interpreter) - ); + if (interpreter) { + language = languages.find((language) => + language.interpreters?.includes(interpreter) + ); + } } - return language && language.parsers[0]; + return language?.parsers[0]; } export { normalize, hiddenDefaults, inferParser }; diff --git a/src/main/range-util.js b/src/main/range-util.js index e6afcb93e..34fc4ec5a 100644 --- a/src/main/range-util.js +++ b/src/main/range-util.js @@ -22,7 +22,7 @@ function dropRootParents(parents) { let lastParentIndex = parents.length - 1; for (;;) { const parent = parents[lastParentIndex]; - if (parent && (parent.type === "Program" || parent.type === "File")) { + if (parent?.type === "Program" || parent?.type === "File") { lastParentIndex--; } else { break; @@ -174,7 +174,7 @@ function isSourceElement(opts, node, parentNode) { case "espree": case "meriyah": case "__babel_estree": - return isJsSourceElement(node.type, parentNode && parentNode.type); + return isJsSourceElement(node.type, parentNode?.type); case "json": case "json5": case "json-stringify": diff --git a/src/main/support.js b/src/main/support.js index 8bc200fe5..d3d14e6a0 100644 --- a/src/main/support.js +++ b/src/main/support.js @@ -51,9 +51,7 @@ function getSupportInfo({ const pluginDefaults = Object.fromEntries( plugins .filter( - (plugin) => - plugin.defaultOptions && - plugin.defaultOptions[option.name] !== undefined + (plugin) => plugin.defaultOptions?.[option.name] !== undefined ) .map((plugin) => [plugin.name, plugin.defaultOptions[option.name]]) ); @@ -83,9 +81,7 @@ function collectParsersFromLanguages(option, languages, plugins) { for (const value of language.parsers) { if (!existingValues.has(value)) { existingValues.add(value); - const plugin = plugins.find( - (plugin) => plugin.parsers && plugin.parsers[value] - ); + const plugin = plugins.find((plugin) => plugin.parsers?.[value]); let description = language.name; if (plugin && plugin.name) { description += ` (plugin: ${plugin.name})`; diff --git a/src/utils/infer-parser-by-language.js b/src/utils/infer-parser-by-language.js index 3dcdf7d21..b258d71a1 100644 --- a/src/utils/infer-parser-by-language.js +++ b/src/utils/infer-parser-by-language.js @@ -4,13 +4,8 @@ function inferParserByLanguage(language, options) { const { languages } = getSupportInfo({ plugins: options.plugins }); const matched = languages.find(({ name }) => name.toLowerCase() === language) || - languages.find( - ({ aliases }) => Array.isArray(aliases) && aliases.includes(language) - ) || - languages.find( - ({ extensions }) => - Array.isArray(extensions) && extensions.includes(`.${language}`) - ); + languages.find(({ aliases }) => aliases?.includes(language)) || + languages.find(({ extensions }) => extensions?.includes(`.${language}`)); return matched && matched.parsers[0]; } diff --git a/src/utils/text/skip-newline.js b/src/utils/text/skip-newline.js index 45464ee0f..9ea491a28 100644 --- a/src/utils/text/skip-newline.js +++ b/src/utils/text/skip-newline.js @@ -10,7 +10,7 @@ * @returns {number | false} */ function skipNewline(text, index, opts) { - const backwards = opts && opts.backwards; + const backwards = Boolean(opts?.backwards); if (index === false) { return false; } diff --git a/src/utils/text/skip.js b/src/utils/text/skip.js index e6ab88e9e..19f97ac9c 100644 --- a/src/utils/text/skip.js +++ b/src/utils/text/skip.js @@ -8,7 +8,7 @@ */ function skip(chars) { return (text, index, opts) => { - const backwards = opts && opts.backwards; + const backwards = Boolean(opts?.backwards); // Allow `skip` functions to be threaded together without having // to check for failures (did someone say monads?).