Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS: Fix import {a as a} and export {a as a} format #9435

Merged
merged 4 commits into from Oct 20, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions changelog_unreleased/javascript/pr-9435.md
@@ -0,0 +1,16 @@
#### Fix `import {a as a}` and `export {a as a}` format (#9435 by @fisker)

<!-- prettier-ignore -->
```js
// Input
import { a as a } from "a";
export { b as b } from "b";

// Prettier stable
import { a } from "a";
export { b } from "b";

// Prettier master
import { a as a } from "a";
export { b as b } from "b";
```
5 changes: 3 additions & 2 deletions src/language-js/printer-estree.js
Expand Up @@ -91,6 +91,7 @@ const {
isNumericLiteral,
isObjectType,
isObjectTypePropertyAFunction,
isSameNode,
isSimpleFlowType,
isSimpleNumber,
isSimpleTemplateLiteral,
Expand Down Expand Up @@ -803,15 +804,15 @@ function printPathNoParens(path, options, print, args) {

parts.push(path.call(print, "imported"));

if (n.local && n.local.name !== n.imported.name) {
if (n.local && !isSameNode(n.local, n.imported, options)) {
parts.push(" as ", path.call(print, "local"));
}

return concat(parts);
case "ExportSpecifier":
parts.push(path.call(print, "local"));

if (n.exported && n.exported.name !== n.local.name) {
if (n.exported && !isSameNode(n.local, n.exported, options)) {
parts.push(" as ", path.call(print, "exported"));
}

Expand Down
25 changes: 23 additions & 2 deletions src/language-js/utils.js
Expand Up @@ -342,8 +342,28 @@ function isGetterOrSetter(node) {
* @param {Node} nodeB
* @returns {boolean}
*/
function sameLocStart(nodeA, nodeB, options) {
return options.locStart(nodeA) === options.locStart(nodeB);
function sameLocStart(nodeA, nodeB, { locStart }) {
return locStart(nodeA) === locStart(nodeB);
}

/**
* @param {Node} nodeA
* @param {Node} nodeB
* @returns {boolean}
*/
function sameLocEnd(nodeA, nodeB, { locEnd }) {
return locEnd(nodeA) === locEnd(nodeB);
}

/**
* @param {Node} nodeA
* @param {Node} nodeB
* @returns {boolean}
*/
function isSameNode(nodeA, nodeB, options) {
Copy link
Member

@thorn0 thorn0 Oct 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

haveSameLoc is a better name. Different nodes can have the same location. E.g.

      {
        "type": "ExpressionStatement",
        "start": 0,
        "end": 3,
        "loc": {
          "start": { "line": 1, "column": 0 },
          "end": { "line": 1, "column": 3 }
        },
        "range": [0, 3],
        "expression": {
          "type": "Identifier",
          "start": 0,
          "end": 3,
          "loc": {
            "start": { "line": 1, "column": 0 },
            "end": { "line": 1, "column": 3 },
            "identifierName": "fff"
          },
          "range": [0, 3],
          "name": "fff"
        }
      }

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed as hasSameLoc 0d515b9

return (
sameLocStart(nodeA, nodeB, options) && sameLocEnd(nodeA, nodeB, options)
);
}

// TODO: This is a bad hack and we need a better way to distinguish between
Expand Down Expand Up @@ -1402,6 +1422,7 @@ module.exports = {
isNumericLiteral,
isObjectType,
isObjectTypePropertyAFunction,
isSameNode,
isSimpleFlowType,
isSimpleNumber,
isSimpleTemplateLiteral,
Expand Down
37 changes: 37 additions & 0 deletions tests/js/export/__snapshots__/jsfmt.spec.js.snap
Expand Up @@ -141,3 +141,40 @@ export {} from ".";

================================================================================
`;

exports[`same-local-and-exported.js - {"bracketSpacing":false} format 1`] = `
====================================options=====================================
bracketSpacing: false
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
export {a} from 'a';
export {b as b} from 'b';
export {c as /* comment */c} from 'c';

=====================================output=====================================
export {a} from "a";
export {b as b} from "b";
export {c as /* comment */ c} from "c";

================================================================================
`;

exports[`same-local-and-exported.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
export {a} from 'a';
export {b as b} from 'b';
export {c as /* comment */c} from 'c';

=====================================output=====================================
export { a } from "a";
export { b as b } from "b";
export { c as /* comment */ c } from "c";

================================================================================
`;
3 changes: 3 additions & 0 deletions tests/js/export/same-local-and-exported.js
@@ -0,0 +1,3 @@
export {a} from 'a';
export {b as b} from 'b';
export {c as /* comment */c} from 'c';
37 changes: 37 additions & 0 deletions tests/js/import/__snapshots__/jsfmt.spec.js.snap
Expand Up @@ -415,3 +415,40 @@ import a, * as b from "a";

================================================================================
`;

exports[`same-local-and-imported.js - {"bracketSpacing":false} format 1`] = `
====================================options=====================================
bracketSpacing: false
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
import {a} from 'a';
import {b as b} from 'b';
import {c as /* comment */c} from 'c';

=====================================output=====================================
import {a} from "a";
import {b as b} from "b";
import {c as /* comment */ c} from "c";

================================================================================
`;

exports[`same-local-and-imported.js format 1`] = `
====================================options=====================================
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
import {a} from 'a';
import {b as b} from 'b';
import {c as /* comment */c} from 'c';

=====================================output=====================================
import { a } from "a";
import { b as b } from "b";
import { c as /* comment */ c } from "c";

================================================================================
`;
3 changes: 3 additions & 0 deletions tests/js/import/same-local-and-imported.js
@@ -0,0 +1,3 @@
import {a} from 'a';
import {b as b} from 'b';
import {c as /* comment */c} from 'c';