Print directive literals verbatim (#1560)
* Print directive literals verbatim
This addresses https://github.com/prettier/prettier/issues/1555,
but doesn't seem to pass the AST_COMPARE=1 tests:
AST_COMPARE=1 npm test -- tests/quotes -t strings
However, running `prettier --debug-check` on the relevant file *does*
work:
prettier tests/quotes/strings.js --debug-check
* Change directive literal quotes if it doesn't contain quotes
This addresses https://github.com/prettier/prettier/pull/1560#discussion_r115396257
From https://github.com/prettier/prettier/issues/1555#issue-227206837:
> It's okay to change the type of quotation marks used, but only if
doing so does not require changing any characters within the directive.
* Don't change directive literal quotes if it contains a backslash
This passes the `--debug-check` tests again:
prettier tests/quotes/strings.js --debug-check
* Try to add regression test for escaped directive literals
This seems not to work, despite the following command having the correct
output:
echo "'\''" | prettier
You can use the following to get an idea of how flow/typescript parse
this:
node -p "JSON.stringify(require('./src/parser').parse('\\'\\\\\'\\'', {parser: 'flow'}), null, 2)"
node -p "JSON.stringify(require('./src/parser').parse('\\'\\\\\'\\'', {parser: 'typescript'}), null, 2)"
* WIP Disable Flow/Typescript for ./tests/directives
We don't yet handle escaped directives for them, but Babylon works.
(similar to 90bf93713c (diff-0de18284f37da79ab8af4e4690919abaR1)
)
* Revert "WIP Disable Flow/Typescript for ./tests/directives"
This reverts commit 2aba6231271f6985a395c31e3df9323e8f3da115.
* Prevent test strings from being parsed as directives
See https://github.com/prettier/prettier/pull/1560#issue-227225960
* Add more escaped directive tests
* Infer DirectiveLiterals from Flow parser
* Don't test TypeScript on directives
See https://github.com/prettier/prettier/pull/1560#issuecomment-300296221
* fixup! Infer DirectiveLiterals from Flow parser
master
parent
ebe85917a3
commit
32d9d68154
|
@ -181,6 +181,20 @@ function genericPrintNoParens(path, options, print, args) {
|
||||||
case "EmptyStatement":
|
case "EmptyStatement":
|
||||||
return "";
|
return "";
|
||||||
case "ExpressionStatement":
|
case "ExpressionStatement":
|
||||||
|
// Detect Flow-parsed directives
|
||||||
|
if (n.directive) {
|
||||||
|
return concat([
|
||||||
|
nodeStr(
|
||||||
|
{
|
||||||
|
type: 'DirectiveLiteral',
|
||||||
|
value: n.expression.value,
|
||||||
|
raw: n.expression.raw
|
||||||
|
},
|
||||||
|
options
|
||||||
|
),
|
||||||
|
semi
|
||||||
|
]);
|
||||||
|
}
|
||||||
return concat([path.call(print, "expression"), semi]); // Babel extension.
|
return concat([path.call(print, "expression"), semi]); // Babel extension.
|
||||||
case "ParenthesizedExpression":
|
case "ParenthesizedExpression":
|
||||||
return concat(["(", path.call(print, "expression"), ")"]);
|
return concat(["(", path.call(print, "expression"), ")"]);
|
||||||
|
@ -3831,6 +3845,7 @@ function nodeStr(node, options) {
|
||||||
const alternate = preferred === single ? double : single;
|
const alternate = preferred === single ? double : single;
|
||||||
|
|
||||||
let shouldUseAlternateQuote = false;
|
let shouldUseAlternateQuote = false;
|
||||||
|
let canChangeDirectiveQuotes = !rawContent.includes('\\');
|
||||||
|
|
||||||
// If `rawContent` contains at least one of the quote preferred for enclosing
|
// If `rawContent` contains at least one of the quote preferred for enclosing
|
||||||
// the string, we might want to enclose with the alternate quote instead, to
|
// the string, we might want to enclose with the alternate quote instead, to
|
||||||
|
@ -3840,12 +3855,23 @@ function nodeStr(node, options) {
|
||||||
const numAlternateQuotes = (rawContent.match(alternate.regex) || []).length;
|
const numAlternateQuotes = (rawContent.match(alternate.regex) || []).length;
|
||||||
|
|
||||||
shouldUseAlternateQuote = numPreferredQuotes > numAlternateQuotes;
|
shouldUseAlternateQuote = numPreferredQuotes > numAlternateQuotes;
|
||||||
|
canChangeDirectiveQuotes = canChangeDirectiveQuotes &&
|
||||||
|
numPreferredQuotes === 0 &&
|
||||||
|
numAlternateQuotes === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
const enclosingQuote = shouldUseAlternateQuote
|
const enclosingQuote = shouldUseAlternateQuote
|
||||||
? alternate.quote
|
? alternate.quote
|
||||||
: preferred.quote;
|
: preferred.quote;
|
||||||
|
|
||||||
|
// Directives are exact code unit sequences, which means that you can't
|
||||||
|
// change the escape sequences they use.
|
||||||
|
// See https://github.com/prettier/prettier/issues/1555
|
||||||
|
// and https://tc39.github.io/ecma262/#directive-prologue
|
||||||
|
if (node.type === 'DirectiveLiteral' && !canChangeDirectiveQuotes) {
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
|
||||||
// It might sound unnecessary to use `makeString` even if `node.raw` already
|
// It might sound unnecessary to use `makeString` even if `node.raw` already
|
||||||
// is enclosed with `enclosingQuote`, but it isn't. `node.raw` could contain
|
// is enclosed with `enclosingQuote`, but it isn't. `node.raw` could contain
|
||||||
// unnecessary escapes (such as in `"\'"`). Always using `makeString` makes
|
// unnecessary escapes (such as in `"\'"`). Always using `makeString` makes
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`escaped.js 1`] = `
|
||||||
|
'\\'';
|
||||||
|
'\\"';
|
||||||
|
"\\'";
|
||||||
|
"\\"";
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
'\\'';
|
||||||
|
'\\"';
|
||||||
|
"\\'";
|
||||||
|
"\\"";
|
||||||
|
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`last-line-0.js 1`] = `
|
exports[`last-line-0.js 1`] = `
|
||||||
'use strict';~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
'use strict';~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
'\'';
|
||||||
|
'\"';
|
||||||
|
"\'";
|
||||||
|
"\"";
|
|
@ -1 +1 @@
|
||||||
run_spec(__dirname, null, ["typescript", "babylon"]);
|
run_spec(__dirname, null, ["babylon"]);
|
||||||
|
|
|
@ -31,6 +31,10 @@ function b(object, key) {
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`strings.js 1`] = `
|
exports[`strings.js 1`] = `
|
||||||
|
// Prevent strings from being parsed as directives
|
||||||
|
// See https://github.com/prettier/prettier/pull/1560#issue-227225960
|
||||||
|
0;
|
||||||
|
|
||||||
// Every string will be changed to double quotes, unless we end up with fewer
|
// Every string will be changed to double quotes, unless we end up with fewer
|
||||||
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
||||||
// option is true).
|
// option is true).
|
||||||
|
@ -101,6 +105,10 @@ exports[`strings.js 1`] = `
|
||||||
"var backslash = \\"\\\\\\", doubleQuote = '\\"';"
|
"var backslash = \\"\\\\\\", doubleQuote = '\\"';"
|
||||||
'var backslash = "\\\\", doubleQuote = \\'"\\';'
|
'var backslash = "\\\\", doubleQuote = \\'"\\';'
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Prevent strings from being parsed as directives
|
||||||
|
// See https://github.com/prettier/prettier/pull/1560#issue-227225960
|
||||||
|
0;
|
||||||
|
|
||||||
// Every string will be changed to double quotes, unless we end up with fewer
|
// Every string will be changed to double quotes, unless we end up with fewer
|
||||||
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
||||||
// option is true).
|
// option is true).
|
||||||
|
@ -161,6 +169,10 @@ exports[`strings.js 1`] = `
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`strings.js 2`] = `
|
exports[`strings.js 2`] = `
|
||||||
|
// Prevent strings from being parsed as directives
|
||||||
|
// See https://github.com/prettier/prettier/pull/1560#issue-227225960
|
||||||
|
0;
|
||||||
|
|
||||||
// Every string will be changed to double quotes, unless we end up with fewer
|
// Every string will be changed to double quotes, unless we end up with fewer
|
||||||
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
||||||
// option is true).
|
// option is true).
|
||||||
|
@ -231,6 +243,10 @@ exports[`strings.js 2`] = `
|
||||||
"var backslash = \\"\\\\\\", doubleQuote = '\\"';"
|
"var backslash = \\"\\\\\\", doubleQuote = '\\"';"
|
||||||
'var backslash = "\\\\", doubleQuote = \\'"\\';'
|
'var backslash = "\\\\", doubleQuote = \\'"\\';'
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Prevent strings from being parsed as directives
|
||||||
|
// See https://github.com/prettier/prettier/pull/1560#issue-227225960
|
||||||
|
0;
|
||||||
|
|
||||||
// Every string will be changed to double quotes, unless we end up with fewer
|
// Every string will be changed to double quotes, unless we end up with fewer
|
||||||
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
||||||
// option is true).
|
// option is true).
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// Prevent strings from being parsed as directives
|
||||||
|
// See https://github.com/prettier/prettier/pull/1560#issue-227225960
|
||||||
|
0;
|
||||||
|
|
||||||
// Every string will be changed to double quotes, unless we end up with fewer
|
// Every string will be changed to double quotes, unless we end up with fewer
|
||||||
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
// escaped quotes by using single quotes. (Vice versa if the "singleQuote"
|
||||||
// option is true).
|
// option is true).
|
||||||
|
|
Loading…
Reference in New Issue