Use babylon.parseExpression for JSON (#2476)

* Add comments showing parser arguments

Since this is how they are invoked, the comments make it easier to maintain.

* Use babylon.parseExpression for JSON

See https://github.com/prettier/prettier/issues/2378#issuecomment-314600778

Note that this doesn't yet print comments:

    echo '{/*comment*/"K":"V"}' | ./bin/prettier.js --parser json

* Remove parser-json.js

This reduces duplicate code in the built package.
See https://github.com/prettier/prettier/pull/2476#pullrequestreview-50181398

* Add test with block comment in JSON

* Fix test with block comment in JSON

* Add test with line comment in JSON

* Don't build now-redundant parser-json.js
This commit is contained in:
Joseph Frazier authored and Lucas Azzola committed 2017-07-24 11:43:49 +10:00
1 parent 781ba9580a
commit a78d1389f6
20 files changed
+74 -120

No files matched your search

+6 -3
View File
@@ -2,7 +2,7 @@
const createError = require("./parser-create-error");
function parse(text) {
function parse(text, parsers, opts) {
// Inline the require to avoid loading all the JS if we don't use it
const babylon = require("babylon");
@@ -27,12 +27,15 @@ function parse(text) {
]
};
const parseMethod =
opts && opts.parser === "json" ? "parseExpression" : "parse";
let ast;
try {
ast = babylon.parse(text, babylonOptions);
ast = babylon[parseMethod](text, babylonOptions);
} catch (originalError) {
try {
ast = babylon.parse(
ast = babylon[parseMethod](
text,
Object.assign({}, babylonOptions, { strictMode: false })
);
+1 -1
View File
@@ -3,7 +3,7 @@
const createError = require("./parser-create-error");
const includeShebang = require("./parser-include-shebang");
function parse(text) {
function parse(text /*, parsers, opts*/) {
// Fixes Node 4 issue (#1986)
"use strict"; // eslint-disable-line
// Inline the require to avoid loading all the JS if we don't use it
+1 -1
View File
@@ -34,7 +34,7 @@ function removeTokens(node) {
return node;
}
function parse(text) {
function parse(text /*, parsers, opts*/) {
// Inline the require to avoid loading all the JS if we don't use it
const parser = require("graphql/language");
try {
-82
View File
@@ -1,82 +0,0 @@
"use strict";
const createError = require("./parser-create-error");
function parse(text) {
const jsonToAst = require("json-to-ast");
try {
const ast = jsonToAst(text);
return toBabylon(ast);
} catch (err) {
const firstNewlineIndex = err.message.indexOf("\n");
const firstLine = err.message.slice(0, firstNewlineIndex);
const lastSpaceIndex = firstLine.lastIndexOf(" ");
const message = firstLine.slice(0, lastSpaceIndex);
const locString = firstLine.slice(lastSpaceIndex + 1);
const lineCol = locString.split(":").map(Number);
throw createError("(json-to-ast) " + message, {
start: {
line: lineCol[0],
column: lineCol[1]
}
});
}
}
function toBabylon(node) {
const typeMap = {
object: "ObjectExpression",
property: "ObjectProperty",
identifier: "json-identifier",
array: "ArrayExpression"
};
const result = {
type: typeMap[node.type],
start: node.loc.start.offset,
end: node.loc.end.offset,
loc: node.loc
};
switch (node.type) {
case "object":
return Object.assign(result, {
properties: node.children.map(toBabylon)
});
case "property":
return Object.assign(result, {
key: toBabylon(node.key),
value: toBabylon(node.value)
});
case "identifier":
return Object.assign(result, {
value: node.value
});
case "array":
return Object.assign(result, {
elements: node.children.map(toBabylon)
});
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, {
type: type,
value: value,
extra: { raw: node.rawValue }
});
}
}
}
module.exports = parse;
+1 -1
View File
@@ -2,7 +2,7 @@
// const createError = require("./parser-create-error");
function parse(text) {
function parse(text /*, parsers, opts*/) {
// Inline the require to avoid loading all the JS if we don't use it
const parse5 = require("parse5");
try {
+1 -1
View File
@@ -208,7 +208,7 @@ function requireParser(isSCSS) {
return require("postcss-less");
}
function parse(text) {
function parse(text /*, parsers, opts*/) {
const isLikelySCSS = !!text.match(/(\w\s*: [^}:]+|#){|@import[^\n]+(url|,)/);
try {
return parseWithParser(requireParser(isLikelySCSS), text);
+1 -1
View File
@@ -3,7 +3,7 @@
const createError = require("./parser-create-error");
const includeShebang = require("./parser-include-shebang");
function parse(text) {
function parse(text /*, parsers, opts*/) {
const jsx = isProbablyJsx(text);
let ast;
try {
+1 -1
View File
@@ -22,7 +22,7 @@ const parsers = {
return eval("require")("./parser-postcss");
},
get json() {
return eval("require")("./parser-json");
return eval("require")("./parser-babylon");
}
};
+6 -3
View File
@@ -2636,8 +2636,6 @@ function genericPrintNoParens(path, options, print, args) {
return path.call(bodyPath => {
return printStatementSequence(bodyPath, options, print);
}, "body");
case "json-identifier":
return '"' + n.value + '"';
default:
/* istanbul ignore next */
@@ -2709,7 +2707,12 @@ function printPropertyKey(path, options, print) {
const node = path.getNode();
const key = node.key;
if (isStringLiteral(key) && isIdentifierName(key.value) && !node.computed) {
if (
isStringLiteral(key) &&
isIdentifierName(key.value) &&
!node.computed &&
options.parser !== "json"
) {
// 'a' -> a
return path.call(
keyPath => comments.printComments(keyPath, () => key.value, options),