From 5a0e33cc84fd59e20a0fcc1d055300a97b595689 Mon Sep 17 00:00:00 2001 From: Georgii Dolzhykov Date: Fri, 29 May 2020 07:29:09 +0300 Subject: [PATCH] fix(range): improve detection of JS source elements (#8419) * fix(range): improve detection of JS source elements * Add changelog entry * Remove unneeded comment * Add more types and update snapshots --- changelog_unreleased/javascript/pr-8419.md | 18 ++++++++ src/main/range-util.js | 45 +++++-------------- .../js/range/__snapshots__/jsfmt.spec.js.snap | 17 +++++++ tests/js/range/directive.js | 2 + .../range/__snapshots__/jsfmt.spec.js.snap | 19 ++++++++ tests/typescript/range/export-assignment.ts | 3 ++ 6 files changed, 71 insertions(+), 33 deletions(-) create mode 100644 changelog_unreleased/javascript/pr-8419.md create mode 100644 tests/js/range/directive.js create mode 100644 tests/typescript/range/export-assignment.ts diff --git a/changelog_unreleased/javascript/pr-8419.md b/changelog_unreleased/javascript/pr-8419.md new file mode 100644 index 000000000..f3a7d5794 --- /dev/null +++ b/changelog_unreleased/javascript/pr-8419.md @@ -0,0 +1,18 @@ +#### Improve detection of source elements for range formatting ([#8419](https://github.com/prettier/prettier/pull/8419) by [@thorn0](https://github.com/thorn0)) + +Not all statement types were detected (read [here](https://prettier.io/docs/en/options.html#range) how range formatting works in Prettier). + + +```jsx +// Input +for (const element of list) { /* ... */ } +// ^^^^^^^^^^^^^^^^^^^^^^ ← range + +// Prettier stable +for (const element of list) { /* ... */ } + +// Prettier master +for (const element of list) { + /* ... */ +} +``` diff --git a/src/main/range-util.js b/src/main/range-util.js index 623e72f4d..a572a3c93 100644 --- a/src/main/range-util.js +++ b/src/main/range-util.js @@ -70,39 +70,18 @@ function findNodeAtOffset(node, offset, options, predicate, parentNodes = []) { } // See https://www.ecma-international.org/ecma-262/5.1/#sec-A.5 +function isJsSourceElement(type) { + return ( + type === "Directive" || + type === "TypeAlias" || + type === "TSExportAssignment" || + type.startsWith("Declare") || + type.startsWith("TSDeclare") || + type.endsWith("Statement") || + type.endsWith("Declaration") + ); +} -// JS and JS like to avoid repetitions -const jsSourceElements = new Set([ - "FunctionDeclaration", - "BlockStatement", - "BreakStatement", - "ContinueStatement", - "DebuggerStatement", - "DoWhileStatement", - "EmptyStatement", - "ExpressionStatement", - "ForInStatement", - "ForStatement", - "IfStatement", - "LabeledStatement", - "ReturnStatement", - "SwitchStatement", - "ThrowStatement", - "TryStatement", - "VariableDeclaration", - "WhileStatement", - "WithStatement", - "ClassDeclaration", // ES 2015 - "ImportDeclaration", // Module - "ExportDefaultDeclaration", // Module - "ExportNamedDeclaration", // Module - "ExportAllDeclaration", // Module - "TypeAlias", // Flow - "InterfaceDeclaration", // Flow, TypeScript - "TypeAliasDeclaration", // TypeScript - "ExportAssignment", // TypeScript - "ExportDeclaration", // TypeScript -]); const jsonSourceElements = new Set([ "ObjectExpression", "ArrayExpression", @@ -139,7 +118,7 @@ function isSourceElement(opts, node) { case "babel-flow": case "babel-ts": case "typescript": - return jsSourceElements.has(node.type); + return isJsSourceElement(node.type); case "json": return jsonSourceElements.has(node.type); case "graphql": diff --git a/tests/js/range/__snapshots__/jsfmt.spec.js.snap b/tests/js/range/__snapshots__/jsfmt.spec.js.snap index 9bb8f6b79..a842fb8f2 100644 --- a/tests/js/range/__snapshots__/jsfmt.spec.js.snap +++ b/tests/js/range/__snapshots__/jsfmt.spec.js.snap @@ -51,6 +51,23 @@ function f() { ================================================================================ `; +exports[`directive.js format 1`] = ` +====================================options===================================== +parsers: ["babel", "flow", "typescript"] +printWidth: 80 + | | printWidth +=====================================input====================================== +> 1 | 'aaa'; + | ^ + 2 | 'bbb'; + 3 | +=====================================output===================================== +"aaa"; +'bbb'; + +================================================================================ +`; + exports[`function-declaration.js format 1`] = ` ====================================options===================================== parsers: ["babel", "flow", "typescript"] diff --git a/tests/js/range/directive.js b/tests/js/range/directive.js new file mode 100644 index 000000000..6c0f1341d --- /dev/null +++ b/tests/js/range/directive.js @@ -0,0 +1,2 @@ +<<>>'<<>>aaa'; +'bbb'; diff --git a/tests/typescript/range/__snapshots__/jsfmt.spec.js.snap b/tests/typescript/range/__snapshots__/jsfmt.spec.js.snap index 3f0fc4f28..8adf39df2 100644 --- a/tests/typescript/range/__snapshots__/jsfmt.spec.js.snap +++ b/tests/typescript/range/__snapshots__/jsfmt.spec.js.snap @@ -1,5 +1,24 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`export-assignment.ts format 1`] = ` +====================================options===================================== +parsers: ["typescript"] +printWidth: 80 + | | printWidth +=====================================input====================================== + 1 | f ( ); +> 2 | export = f; + | ^^^ + 3 | g( ) + 4 | +=====================================output===================================== +f ( ); +export = f; +g( ) + +================================================================================ +`; + exports[`issue-4926.ts format 1`] = ` ====================================options===================================== parsers: ["typescript"] diff --git a/tests/typescript/range/export-assignment.ts b/tests/typescript/range/export-assignment.ts new file mode 100644 index 000000000..50ca507ca --- /dev/null +++ b/tests/typescript/range/export-assignment.ts @@ -0,0 +1,3 @@ +f ( ); +export <<>> = <<>> f; +g( )