Skip to content

Commit

Permalink
[prettierx] -- align-object-properties option
Browse files Browse the repository at this point in the history
feature ported from prettier-miscellaneous
(arijs#7 & arijs#8)

with adaptations by @brodybits
(Christopher J. Brody <[email protected]>), including:
* JavaScript tests in es test subdirectory
* not applied with any of the JSON parsers, as verified by json test
  (not applied in case parser matches /json/ pattern)
* --align-object-properties option config & docs adapted
  (copy-pasted) into newer prettier/prettierx project structure
* const shouldBreak hack updated (and reformatted), can now deal
  with an object that is partially but not completely defined
  on the first line, as verified by an additional test object
* extra comment(s) & spacing
* additional testing to ensure that it does not get unwanted padding
  in case an object is on a single line
* hack with fix for object partially but not completely defined
  on the first line, with additional test to verify
* test coverage on babel, flow, and typescript parsers
* test with shorthand object member
* tests_integration updates
* some other added tests
* lint fixes

Co-authored-by: Christopher J. Brody <[email protected]>
Co-authored-by: Joseph Frazier <[email protected]>
Co-authored-by: Rafael Hengles <[email protected]>
Co-authored-by: Ika <[email protected]>
Co-authored-by: Lucas Azzola <[email protected]>
  • Loading branch information
5 people committed Jan 14, 2019
1 parent af67abe commit 1674f7f
Show file tree
Hide file tree
Showing 15 changed files with 467 additions and 3 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ prettierx <options> <file(s)>

| Option | Default value | CLI Override | API Override | Description |
| ---------------------------------------------------- | ------------- | ------------------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------- |
| Align object properties | `false` | `--align-object-properties` | `alignObjectProperties: <bool>` | Align colons in multiline object literals (not applied with any of the JSON parsers). |
| Space before function parentheses | `false` | `--space-before-function-paren` | `spaceBeforeFunctionParen: <bool>` | Put a space before function parenthesis. |
| Spaces around the star (\*\) in generator functions | `false` | `--generator-star-spacing` | `generatorStarSpacing: <bool>` | Add spaces around the star (\*) in generator functions (before and after - from eslint). |
| Spaces around the star (\*\) in `yield*` expressions | `false` | `--yield-star-spacing` | `yieldStarSpacing: <bool>` | Add spaces around the star (\*) in yield\* expressions (before and after - from eslint). |
Expand Down
8 changes: 8 additions & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,14 @@ These options cannot be used with `cursorOffset`.
| `0` | `--range-start <int>` | `rangeStart: <int>` |
| `Infinity` | `--range-end <int>` | `rangeEnd: <int>` |

## Align object properties

Align colons in multiline object literals (not applied with any of the JSON parsers).

| Default | CLI Override | API Override |
| ------- | --------------------------- | ------------------------------- |
| `false` | `--align-object-properties` | `alignObjectProperties: <bool>` |

## Space before function parentheses

Put a space before function parenthesis.
Expand Down
6 changes: 6 additions & 0 deletions src/language-js/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ module.exports = {
oppositeDescription:
"Do not print semicolons, except at the beginning of lines which may need them."
},
alignObjectProperties: {
category: CATEGORY_JAVASCRIPT,
type: "boolean",
default: false,
description: "Align colons in multiline object literals."
},
generatorStarSpacing: {
category: CATEGORY_JAVASCRIPT,
type: "boolean",
Expand Down
75 changes: 73 additions & 2 deletions src/language-js/printer-estree.js
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,65 @@ function genericPrint(path, options, printPath, args) {
return concat(parts);
}

function getPropertyPadding(options, path) {
if (!options.alignObjectProperties) {
return "";
}

if (options.parser.match(/json/)) {
return "";
}

const n = path.getValue();
const type = n.type;

// grandparent node:
const parentObject = path.getParentNode(1);

// THIS IS A HACK:
const shouldBreak = options.originalText
.substring(options.locStart(parentObject), options.locEnd(parentObject))
.match(/\{\s*(\/.*)?\n/);

if (!shouldBreak) {
return "";
}

const nameLength =
type === "Identifier"
? n.name.length
: n.raw
? n.raw.length
: n.extra.raw
? n.extra.raw.length
: undefined;

// FUTURE TBD from arijs/prettier-miscellaneous#10
// (does not seem to be needed to pass the tests):
// if (nameLength === undefined) {
// return "";
// }

const properties = parentObject.properties;
const lengths = properties.map(p => {
if (!p.key) {
return 0;
}
return (
p.key.loc.end.column -
p.key.loc.start.column +
( p.computed ? 2 : 0)
);
});

const maxLength = Math.max.apply(null, lengths);
const padLength = maxLength - nameLength + 1;

const padding = " ".repeat(padLength);

return padding;
}

function hasNewlineBetweenOrAfterDecorators(node, options) {
return (
hasNewlineInRange(
Expand Down Expand Up @@ -1440,10 +1499,22 @@ function printPathNoParens(path, options, print, args) {
parts.push(path.call(print, "value"));
} else {
let printedLeft;
const propertyPadding = path.call(
getPropertyPadding.bind(null, options),
"key"
);
if (n.computed) {
printedLeft = concat(["[", path.call(print, "key"), "]"]);
printedLeft = concat([
"[",
path.call(print, "key"),
"]",
propertyPadding.slice(2)
]);
} else {
printedLeft = printPropertyKey(path, options, print);
printedLeft = concat([
printPropertyKey(path, options, print),
propertyPadding
]);
}
parts.push(
printAssignment(
Expand Down
192 changes: 192 additions & 0 deletions tests/align-object-properties/es/__snapshots__/jsfmt.spec.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`o.js 1`] = `
====================================options=====================================
alignObjectProperties: true
parsers: ["babel", "flow", "typescript"]
printWidth: 80
| printWidth
=====================================input======================================
o = {
[name]: 'value',
2:3,
"k-2":2,
keyasdf:3
}
o = {
[namelonglonglong]: 'value',
2:3,
"k-2":2,
keyasdf:3
}
// with shorthand member:
o = {
shorthand,
[namelonglonglong]: 'value',
2:3,
"k-2":2,
keyasdf:3
}
// with extra-long shorthand member:
o = {
extraLongShorthand,
[name]: 'value',
2:3,
"k-2":2,
keyasdf:3
}
// Ensure this object does not get extra padding:
o = { [name]: 'value', 2:3, "k-2":2, keyasdf:3 }
// Ensure this also does not get extra padding:
o = { [name]: 'value', 2:3, "k-2":2,
keyasdf:3
}
// Ensure this one *does* get the padding:
o = { // with a comment here
[name]: 'value',
2:3,
"k-2":2,
keyasdf:3
}
// with multiple entries on a single line in the input:
o = {
[namelonglonglong]: 'value',
2:3, "k-2":2, keyasdf:3
}
// longer object on a single line:
o = { [namelonglonglong]: 'value', 2:3, "k-2":2, keyasdf:3 }
// with nested object member:
o = {
[name]: 'value',
2:3,
"k-2":2,
nested: {
a:1,
next:2
},
keyasdf:3
}
// with nested object member on a single line
// (which should not get extra padding):
o = {
[name]: 'value',
2:3,
"k-2":2,
nested: { a:1, next:2 },
keyasdf:3
}
// with nested object member which is reformatted onto single line
// (which should not get extra padding):
o = {
[name]: 'value',
2:3,
"k-2":2,
nested: {a:1,
next:2},
keyasdf:3
}
=====================================output=====================================
o = {
[name] : "value",
2 : 3,
"k-2" : 2,
keyasdf : 3
};
o = {
[namelonglonglong] : "value",
2 : 3,
"k-2" : 2,
keyasdf : 3
};
// with shorthand member:
o = {
shorthand,
[namelonglonglong] : "value",
2 : 3,
"k-2" : 2,
keyasdf : 3
};
// with extra-long shorthand member:
o = {
extraLongShorthand,
[name] : "value",
2 : 3,
"k-2" : 2,
keyasdf : 3
};
// Ensure this object does not get extra padding:
o = { [name]: "value", 2: 3, "k-2": 2, keyasdf: 3 };
// Ensure this also does not get extra padding:
o = { [name]: "value", 2: 3, "k-2": 2, keyasdf: 3 };
// Ensure this one *does* get the padding:
o = {
// with a comment here
[name] : "value",
2 : 3,
"k-2" : 2,
keyasdf : 3
};
// with multiple entries on a single line in the input:
o = {
[namelonglonglong] : "value",
2 : 3,
"k-2" : 2,
keyasdf : 3
};
// longer object on a single line:
o = { [namelonglonglong]: "value", 2: 3, "k-2": 2, keyasdf: 3 };
// with nested object member:
o = {
[name] : "value",
2 : 3,
"k-2" : 2,
nested : {
a : 1,
next : 2
},
keyasdf : 3
};
// with nested object member on a single line
// (which should not get extra padding):
o = {
[name] : "value",
2 : 3,
"k-2" : 2,
nested : { a: 1, next: 2 },
keyasdf : 3
};
// with nested object member which is reformatted onto single line
// (which should not get extra padding):
o = {
[name] : "value",
2 : 3,
"k-2" : 2,
nested : { a: 1, next: 2 },
keyasdf : 3
};
================================================================================
`;
3 changes: 3 additions & 0 deletions tests/align-object-properties/es/jsfmt.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
run_spec(__dirname, ["babel", "flow", "typescript"], {
alignObjectProperties: true
});
Loading

0 comments on commit 1674f7f

Please sign in to comment.