Skip to content

Commit

Permalink
babel-core: add options for different parser/generator (babel#3561)
Browse files Browse the repository at this point in the history
* babel-core: add options for different parser/generator

* test for experiemental plugins, other babylon options

* fix passing options into parser

* Fix when no code is provided

* fixup tests

* fix tests again

* use filename and fallback to cwd
  • Loading branch information
hzoo authored and panagosg7 committed Jan 17, 2017
1 parent 9156ae3 commit 2c7c8c7
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 3 deletions.
48 changes: 46 additions & 2 deletions packages/babel-core/src/transformation/file/index.js
Expand Up @@ -21,6 +21,8 @@ import * as util from "../../util";
import path from "path";
import * as t from "babel-types";

import resolve from "../../helpers/resolve";

import blockHoistPlugin from "../internal-plugins/block-hoist";
import shadowFunctionsPlugin from "../internal-plugins/shadow-functions";

Expand Down Expand Up @@ -411,8 +413,35 @@ export default class File extends Store {
}

parse(code: string) {
let parseCode = parse;
let parserOpts = this.opts.parserOpts || this.parserOpts;

if (parserOpts) {
parserOpts = Object.assign({}, this.parserOpts, parserOpts);

if (parserOpts.parser) {
if (typeof parserOpts.parser === "string") {
let dirname = path.dirname(this.opts.filename) || process.cwd();
let parser = resolve(parserOpts.parser, dirname);
if (parser) {
parseCode = require(parser).parse;
} else {
throw new Error(`Couldn't find parser ${parserOpts.parser} with "parse" method relative to directory ${dirname}`);
}
} else {
parseCode = parserOpts.parser;
}

parserOpts.parser = {
parse(source) {
return parse(source, parserOpts);
}
};
}
}

this.log.debug("Parse start");
let ast = parse(code, this.parserOpts);
let ast = parseCode(code, parserOpts);
this.log.debug("Parse stop");
return ast;
}
Expand Down Expand Up @@ -573,9 +602,24 @@ export default class File extends Store {
let result: BabelFileResult = { ast };
if (!opts.code) return this.makeResult(result);
let gen = generate;
if (opts.generatorOpts.generator) {
gen = opts.generatorOpts.generator;
if (typeof gen === "string") {
let dirname = path.dirname(this.opts.filename) || process.cwd();
let generator = resolve(gen, dirname);
if (generator) {
gen = require(generator).print;
} else {
throw new Error(`Couldn't find generator ${gen} with "print" method relative to directory ${dirname}`);
}
}
}
this.log.debug("Generation start");
let _result = generate(ast, opts, this.code);
let _result = gen(ast, opts.generatorOpts ? Object.assign(opts, opts.generatorOpts) : opts, this.code);
result.code = _result.code;
result.map = _result.map;
Expand Down
12 changes: 12 additions & 0 deletions packages/babel-core/src/transformation/file/options/config.js
Expand Up @@ -198,4 +198,16 @@ module.exports = {
default: false,
hidden: true,
},

// Deprecate top level parserOpts
parserOpts: {
description: "Options to pass into the parser, or to change parsers (parserOpts.parser)",
default: false
},

// Deprecate top level generatorOpts
generatorOpts: {
description: "Options to pass into the generator, or to change generators (generatorOpts.generator)",
default: false
}
};
72 changes: 72 additions & 0 deletions packages/babel-core/test/api.js
Expand Up @@ -5,6 +5,7 @@ var sourceMap = require("source-map");
var assert = require("assert");
var File = require("../lib/transformation/file").default;
var Plugin = require("../lib/transformation/plugin");
var generator = require("babel-generator").default;

function assertIgnored(result) {
assert.ok(result.ignored);
Expand All @@ -23,6 +24,77 @@ function transformAsync(code, opts) {
};
}

suite("parser and generator options", function() {
var recast = {
parse: function(code, opts) {
return opts.parser.parse(code);
},
print: function(ast) {
return generator(ast);
}
};

function newTransform(string) {
return babel.transform(string, {
parserOpts: {
parser: recast.parse,
plugins: ["flow"],
allowImportExportEverywhere: true
},
generatorOpts: {
generator: recast.print
}
});
}

test("options", function() {
var string = "original;";
assert.deepEqual(newTransform(string).ast, babel.transform(string).ast);
assert.equal(newTransform(string).code, string);
});

test("experimental syntax", function() {
var experimental = "var a: number = 1;";

assert.deepEqual(newTransform(experimental).ast, babel.transform(experimental, {
parserOpts: {
plugins: ["flow"]
}
}).ast);
assert.equal(newTransform(experimental).code, experimental);

function newTransformWithPlugins(string) {
return babel.transform(string, {
plugins: [__dirname + "/../../babel-plugin-syntax-flow"],
parserOpts: {
parser: recast.parse
},
generatorOpts: {
generator: recast.print
}
});
}

assert.deepEqual(newTransformWithPlugins(experimental).ast, babel.transform(experimental, {
parserOpts: {
plugins: ["flow"]
}
}).ast);
assert.equal(newTransformWithPlugins(experimental).code, experimental);
});

test("other options", function() {
var experimental = "if (true) {\n import a from 'a';\n}";

assert.notEqual(newTransform(experimental).ast, babel.transform(experimental, {
parserOpts: {
allowImportExportEverywhere: true
}
}).ast);
assert.equal(newTransform(experimental).code, experimental);
});
});

suite("api", function () {
test("analyze", function () {
assert.equal(babel.analyse("foobar;").marked.length, 0);
Expand Down
7 changes: 6 additions & 1 deletion packages/babel-generator/src/index.js
Expand Up @@ -93,6 +93,11 @@ function normalizeOptions(code, opts, tokens): Format {
* Determine if input code uses more single or double quotes.
*/
function findCommonStringDelimiter(code, tokens) {
const DEFAULT_STRING_DELIMITER = "double";
if (!code) {
return DEFAULT_STRING_DELIMITER;
}

let occurences = {
single: 0,
double: 0
Expand All @@ -117,7 +122,7 @@ function findCommonStringDelimiter(code, tokens) {
if (occurences.single > occurences.double) {
return "single";
} else {
return "double";
return DEFAULT_STRING_DELIMITER;
}
}

Expand Down

0 comments on commit 2c7c8c7

Please sign in to comment.