Format JSON literals like object literals (#2181)

* Format JSON literals like object literals

Following up on commit a42db30 (https://github.com/prettier/prettier/issues/2173),
this change makes it so that literals in JSON files are formatted as
they would be in an object literal. This normalizes trailing zeroes,
exponential notation, unnecessarily escaped characters, etc.

It works by using babylon to parse literals as expressions, and putting
the result in the AST instead of a `json-literal` node. Since JSON
string literals have to be double-quoted, there's a new
`__prettier__isJson` flag on each node, which is used by the printer to
force double-quotes.

* json: Check options.parser when formatting StringLiteral

This is instead of having a custom AST property. See
https://github.com/prettier/prettier/pull/2181#discussion_r122578251

* multiparser: Use babylon.parseExpression

See https://github.com/prettier/prettier/pull/2181#discussion_r122578354

* json: Don't split result AST node into two

See https://github.com/prettier/prettier/pull/2181#discussion_r122578499

* json: Don't use babylon parser to build expression nodes

See https://github.com/prettier/prettier/pull/2181#discussion_r122579052

* Revert "multiparser: Use babylon.parseExpression"

This reverts commit 3d7a4362880d39fac0cea88b5d0186a29538cf6f.

* Remove unused parameter from babylon parser

* json: Remove unused constructorTypes
master
Joseph Frazier 2017-06-17 20:49:22 -04:00 committed by GitHub
parent 532ac0d3f8
commit 69808cebfb
3 changed files with 27 additions and 16 deletions

View File

@ -29,8 +29,7 @@ function toBabylon(node) {
object: "ObjectExpression",
property: "ObjectProperty",
identifier: "json-identifier",
array: "ArrayExpression",
literal: "json-literal"
array: "ArrayExpression"
};
const result = {
@ -58,10 +57,24 @@ function toBabylon(node) {
return Object.assign(result, {
elements: node.children.map(toBabylon)
});
case "literal":
case "literal": {
const constructorTypes = {
String: "StringLiteral",
Number: "NumericLiteral",
Boolean: "BooleanLiteral"
};
const value = JSON.parse(node.rawValue);
const type = value === null
? "NullLiteral"
: constructorTypes[value.constructor.name];
return Object.assign(result, {
rawValue: node.rawValue
type: type,
value: value,
extra: { raw: node.rawValue }
});
}
}
}

View File

@ -2636,8 +2636,6 @@ function genericPrintNoParens(path, options, print, args) {
}, "body");
case "json-identifier":
return '"' + n.value + '"';
case "json-literal":
return n.rawValue;
default:
throw new Error("unknown type: " + JSON.stringify(n.type));
@ -4144,9 +4142,9 @@ function nodeStr(node, options, isFlowOrTypeScriptDirectiveLiteral) {
canChangeDirectiveQuotes = true;
}
const enclosingQuote = shouldUseAlternateQuote
? alternate.quote
: preferred.quote;
const enclosingQuote = options.parser === "json"
? double.quote
: shouldUseAlternateQuote ? alternate.quote : preferred.quote;
// Directives are exact code unit sequences, which means that you can't
// change the escape sequences they use.

View File

@ -82,17 +82,17 @@ exports[`pass1.json 1`] = `
null,
{
"integer": 1234567890,
"real": -9876.543210,
"real": -9876.54321,
"e": 0.123456789e-12,
"E": 1.234567890E+34,
"": 23456789012E66,
"E": 1.23456789e34,
"": 23456789012e66,
"zero": 0,
"one": 1,
"space": " ",
"quote": "\\"",
"backslash": "\\\\",
"controls": "\\b\\f\\n\\r\\t",
"slash": "/ & \\/",
"slash": "/ & /",
"alpha": "abcdefghijklmnopqrstuvwyz",
"ALPHA": "ABCDEFGHIJKLMNOPQRSTUVWYZ",
"digit": "0123456789",
@ -121,9 +121,9 @@ exports[`pass1.json 1`] = `
1e1,
0.1e1,
1e-1,
1e00,
2e+00,
2e-00,
1,
2,
2,
"rosebud"
]
`;