Proper indentation for template literals (#1385)

Right now, expressions inside of template literals are have the level of indentation of the start of the template literal. But oftentimes, expressions are nested inside of template literals and therefore the expression should have this level of nesting.

The heuristic i'm using to decide when to use the template literal nesting is if it's not the first line and if there isn't another expression before on the same line.
This commit is contained in:
Christopher Chedeau authored and GitHub committed 2017-05-01 14:28:11 -07:00
1 parent c521406385
commit 13f05fb763
7 files changed
+247 -1

No files matched your search

+10
View File
@@ -21,6 +21,16 @@ function makeIndent(ind) {
}
function makeAlign(ind, n) {
if (n === -Infinity) {
return {
indent: 0,
align: {
spaces: 0,
tabs: 0
}
};
}
return {
indent: ind.indent,
align: {
+43 -1
View File
@@ -1506,9 +1506,51 @@ function genericPrintNoParens(path, options, print, args) {
parts.push(print(childPath));
if (i < expressions.length) {
// For a template literal of the following form:
// `someQuery {
// ${call({
// a,
// b,
// })}
// }`
// the expression is on its own line (there is a \n in the previous
// quasi literal), therefore we want to indent the JavaScript
// expression inside at the beginning of ${ instead of the beginning
// of the `.
let size = 0;
const value = childPath.getValue().value.raw;
const index = value.lastIndexOf('\n');
const tabWidth = options.tabWidth;
if (index !== -1) {
for (let i = index + 1; i < value.length; ++i) {
if (value[i] === '\t') {
// Tabs behave in a way that they are aligned to the nearest
// multiple of tabWidth:
// 0 -> 4, 1 -> 4, 2 -> 4, 3 -> 4
// 4 -> 8, 5 -> 8, 6 -> 8, 7 -> 8 ...
size = size + tabWidth - size % tabWidth;
} else {
size++;
}
}
}
let aligned = removeLines(expressions[i]);
if (size > 0) {
// Use indent to add tabs for all the levels of tabs we need
for (var i = 0; i < Math.floor(size / tabWidth); ++i) {
aligned = indent(aligned);
}
// Use align for all the spaces that are needed
aligned = align(size % tabWidth, aligned);
// size is absolute from 0 and not relative to the current
// indentation, so we use -Infinity to reset the indentation to 0
aligned = align(-Infinity, aligned);
}
parts.push(
"${",
removeLines(expressions[i]),
aligned,
lineSuffixBoundary,
"}"
);
@@ -82,6 +82,45 @@ var x = {
`;
exports[`graphql.js 1`] = `
module.exports = Relay.createContainer(
// ...
{
fragments: {
nodes: ({solution_type, time_frame}) => Relay.QL\`
fragment on RelatedNode @relay(plural: true) {
__typename
\${OptimalSolutionsSection
.getFragment(
'node',
{solution_type, time_frame},
)
}
}
\`,
},
},
);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
module.exports = Relay.createContainer(
// ...
{
fragments: {
nodes: ({ solution_type, time_frame }) => Relay.QL\`
fragment on RelatedNode @relay(plural: true) {
__typename
\${OptimalSolutionsSection.getFragment("node", {
solution_type,
time_frame
})}
}
\`
}
}
);
`;
exports[`parenthesis.js 1`] = `
// "ArrowFunctionExpression"
(() => {})\`\`;
+18
View File
@@ -0,0 +1,18 @@
module.exports = Relay.createContainer(
// ...
{
fragments: {
nodes: ({solution_type, time_frame}) => Relay.QL`
fragment on RelatedNode @relay(plural: true) {
__typename
${OptimalSolutionsSection
.getFragment(
'node',
{solution_type, time_frame},
)
}
}
`,
},
},
);
@@ -0,0 +1,119 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`indent.js 1`] = `
\`
Mixed tabs and characters:
\${() => {a}}
. \${() => {a}}
.. \${() => {a}}
... \${() => {a}}
.... \${() => {a}}
..... \${() => {a}}
...... \${() => {a}}
....... \${() => {a}}
........ \${() => {a}}
Tabs:
\${() => {a}}
\${() => {a}}
\`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\`
Mixed tabs and characters:
\${() => {
a;
}}
. \${() => {
a;
}}
.. \${() => {
a;
}}
... \${() => {
a;
}}
.... \${() => {
a;
}}
..... \${() => {
a;
}}
...... \${() => {
a;
}}
....... \${() => {
a;
}}
........ \${() => {
a;
}}
Tabs:
\${() => {
a;
}}
\${() => {
a;
}}
\`;
`;
exports[`indent.js 2`] = `
\`
Mixed tabs and characters:
\${() => {a}}
. \${() => {a}}
.. \${() => {a}}
... \${() => {a}}
.... \${() => {a}}
..... \${() => {a}}
...... \${() => {a}}
....... \${() => {a}}
........ \${() => {a}}
Tabs:
\${() => {a}}
\${() => {a}}
\`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\`
Mixed tabs and characters:
\${() => {
a;
}}
. \${() => {
a;
}}
.. \${() => {
a;
}}
... \${() => {
a;
}}
.... \${() => {
a;
}}
..... \${() => {
a;
}}
...... \${() => {
a;
}}
....... \${() => {
a;
}}
........ \${() => {
a;
}}
Tabs:
\${() => {
a;
}}
\${() => {
a;
}}
\`;
`;
+16
View File
@@ -0,0 +1,16 @@
`
Mixed tabs and characters:
${() => {a}}
. ${() => {a}}
.. ${() => {a}}
... ${() => {a}}
.... ${() => {a}}
..... ${() => {a}}
...... ${() => {a}}
....... ${() => {a}}
........ ${() => {a}}
Tabs:
${() => {a}}
${() => {a}}
`
+2
View File
@@ -0,0 +1,2 @@
run_spec(__dirname, null, ["typescript"]);
run_spec(__dirname, {useTabs: true, tabWidth: 8}, ["typescript"]);