Skip to content

Commit

Permalink
Merge pull request #7955 from loganfsmyth/typescript-filename-required
Browse files Browse the repository at this point in the history
Verify that files are .ts/.tsx before treating as Typescript files.
  • Loading branch information
loganfsmyth committed May 23, 2018
2 parents 5e00c96 + f2882d5 commit eb3334a
Show file tree
Hide file tree
Showing 35 changed files with 235 additions and 78 deletions.
36 changes: 19 additions & 17 deletions packages/babel-core/src/config/validation/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,27 +57,10 @@ const NONPRESET_VALIDATORS: ValidatorSet = {
extends: (assertString: Validator<
$PropertyType<ValidatedOptions, "extends">,
>),
env: (assertEnvSet: Validator<$PropertyType<ValidatedOptions, "env">>),
ignore: (assertIgnoreList: Validator<
$PropertyType<ValidatedOptions, "ignore">,
>),
only: (assertIgnoreList: Validator<$PropertyType<ValidatedOptions, "only">>),
overrides: (assertOverridesList: Validator<
$PropertyType<ValidatedOptions, "overrides">,
>),

// We could limit these to 'overrides' blocks, but it's not clear why we'd
// bother, when the ability to limit a config to a specific set of files
// is a fairly general useful feature.
test: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "test">,
>),
include: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "include">,
>),
exclude: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "exclude">,
>),
};

const COMMON_VALIDATORS: ValidatorSet = {
Expand All @@ -96,6 +79,25 @@ const COMMON_VALIDATORS: ValidatorSet = {
passPerPreset: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "passPerPreset">,
>),

env: (assertEnvSet: Validator<$PropertyType<ValidatedOptions, "env">>),
overrides: (assertOverridesList: Validator<
$PropertyType<ValidatedOptions, "overrides">,
>),

// We could limit these to 'overrides' blocks, but it's not clear why we'd
// bother, when the ability to limit a config to a specific set of files
// is a fairly general useful feature.
test: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "test">,
>),
include: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "include">,
>),
exclude: (assertConfigApplicableTest: Validator<
$PropertyType<ValidatedOptions, "exclude">,
>),

retainLines: (assertBoolean: Validator<
$PropertyType<ValidatedOptions, "retainLines">,
>),
Expand Down
72 changes: 28 additions & 44 deletions packages/babel-helper-fixtures/src/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import assert from "assert";
import cloneDeep from "lodash/cloneDeep";
import trimEnd from "lodash/trimEnd";
import resolve from "try-resolve";
Expand Down Expand Up @@ -56,6 +55,24 @@ function shouldIgnore(name, blacklist?: Array<string>) {
);
}

const EXTENSIONS = [".js", ".mjs", ".ts", ".tsx"];

function findFile(filepath: string, allowJSON: boolean) {
const matches = [];

for (const ext of EXTENSIONS.concat(allowJSON ? ".json" : [])) {
const name = filepath + ext;

if (fs.existsSync(name)) matches.push(name);
}

if (matches.length > 1) {
throw new Error(`Found conflicting file matches: ${matches.join(", ")}`);
}

return matches[0] || filepath + ".js";
}

export default function get(entryLoc): Array<Suite> {
const suites = [];

Expand Down Expand Up @@ -84,54 +101,25 @@ export default function get(entryLoc): Array<Suite> {
}

function push(taskName, taskDir) {
let actualLocAlias = suiteName + "/" + taskName + "/input.js";
let expectLocAlias = suiteName + "/" + taskName + "/output.js";
let execLocAlias = suiteName + "/" + taskName + "/exec.js";

let actualLoc = taskDir + "/input.js";
let expectLoc = taskDir + "/output.js";
let execLoc = taskDir + "/exec.js";

const hasExecJS = fs.existsSync(execLoc);
const hasExecMJS = fs.existsSync(asMJS(execLoc));
if (hasExecMJS) {
assert(!hasExecJS, `${asMJS(execLoc)}: Found conflicting .js`);
const actualLoc = findFile(taskDir + "/input");
const expectLoc = findFile(taskDir + "/output", true /* allowJSON */);
let execLoc = findFile(taskDir + "/exec");

execLoc = asMJS(execLoc);
execLocAlias = asMJS(execLocAlias);
}

const hasExpectJS = fs.existsSync(expectLoc);
const hasExpectMJS = fs.existsSync(asMJS(expectLoc));
if (hasExpectMJS) {
assert(!hasExpectJS, `${asMJS(expectLoc)}: Found conflicting .js`);

expectLoc = asMJS(expectLoc);
expectLocAlias = asMJS(expectLocAlias);
}

const hasActualJS = fs.existsSync(actualLoc);
const hasActualMJS = fs.existsSync(asMJS(actualLoc));
if (hasActualMJS) {
assert(!hasActualJS, `${asMJS(actualLoc)}: Found conflicting .js`);

actualLoc = asMJS(actualLoc);
actualLocAlias = asMJS(actualLocAlias);
}
const actualLocAlias =
suiteName + "/" + taskName + "/" + path.basename(actualLoc);
const expectLocAlias =
suiteName + "/" + taskName + "/" + path.basename(actualLoc);
let execLocAlias =
suiteName + "/" + taskName + "/" + path.basename(actualLoc);

if (fs.statSync(taskDir).isFile()) {
const ext = path.extname(taskDir);
if (ext !== ".js" && ext !== ".mjs") return;
if (EXTENSIONS.indexOf(ext) === -1) return;

execLoc = taskDir;
execLocAlias = suiteName + "/" + taskName;
}

if (resolve.relative(expectLoc + "on")) {
expectLoc += "on";
expectLocAlias += "on";
}

const taskOpts = cloneDeep(suite.options);

const taskOptsLoc = resolve(taskDir + "/options");
Expand Down Expand Up @@ -222,10 +210,6 @@ export function multiple(entryLoc, ignore?: Array<string>) {
return categories;
}

function asMJS(filepath) {
return filepath.replace(/\.js$/, ".mjs");
}

export function readFile(filename) {
if (fs.existsSync(filename)) {
let file = trimEnd(fs.readFileSync(filename, "utf8"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,10 @@ function run(task) {
newOpts.presets,
optionsDir,
).map(function(val) {
if (val.length > 2) {
if (val.length > 3) {
throw new Error(
"Unexpected extra options " +
JSON.stringify(val.slice(2)) +
JSON.stringify(val.slice(3)) +
" passed to preset.",
);
}
Expand Down
10 changes: 10 additions & 0 deletions packages/babel-plugin-syntax-flow/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ export default declare((api, options) => {

return {
manipulateOptions(opts, parserOpts) {
// If the file has already enabled TS, assume that this is not a
// valid Flowtype file.
if (
parserOpts.plugins.some(
p => (Array.isArray(p) ? p[0] : p) === "typescript",
)
) {
return;
}

parserOpts.plugins.push(["flow", { all }]);
},
};
Expand Down
10 changes: 10 additions & 0 deletions packages/babel-plugin-syntax-jsx/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ export default declare(api => {

return {
manipulateOptions(opts, parserOpts) {
// If the Typescript plugin already ran, it will have decided whether
// or not this is a TSX file.
if (
parserOpts.plugins.some(
p => (Array.isArray(p) ? p[0] : p) === "typescript",
)
) {
return;
}

parserOpts.plugins.push("jsx");
},
};
Expand Down
30 changes: 29 additions & 1 deletion packages/babel-plugin-syntax-typescript/src/index.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,43 @@
import { declare } from "@babel/helper-plugin-utils";

export default declare(api => {
function removePlugin(plugins, name) {
const indices = [];
plugins.forEach((plugin, i) => {
const n = Array.isArray(plugin) ? plugin[0] : plugin;

if (n === name) {
indices.unshift(i);
}
});

for (const i of indices) {
plugins.splice(i, 1);
}
}

export default declare((api, { isTSX }) => {
api.assertVersion(7);

return {
manipulateOptions(opts, parserOpts) {
const { plugins } = parserOpts;
// If the Flow syntax plugin already ran, remove it since Typescript
// takes priority.
removePlugin(plugins, "flow");

// If the JSX syntax plugin already ran, remomove it because JSX handling
// in TS depends on the extensions, and is purely dependent on 'isTSX'.
removePlugin(plugins, "jsx");

parserOpts.plugins.push(
"typescript",
"objectRestSpread",
"classProperties",
);

if (isTSX) {
parserOpts.plugins.push("jsx");
}
},
};
});
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"plugins": ["syntax-jsx", ["transform-typescript", { "jsxPragma": "h" }]]
"plugins": [["transform-typescript", { "jsxPragma": "h", "isTSX": true }]]
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"plugins": ["syntax-jsx", "transform-typescript"]
"plugins": [["transform-typescript", { "isTSX": true }]]
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"plugins": ["syntax-jsx", "transform-typescript"]
"plugins": [["transform-typescript", { "isTSX": true }]]
}
1 change: 0 additions & 1 deletion packages/babel-preset-react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"main": "lib/index.js",
"dependencies": {
"@babel/helper-plugin-utils": "7.0.0-beta.47",
"@babel/plugin-syntax-jsx": "7.0.0-beta.47",
"@babel/plugin-transform-react-display-name": "7.0.0-beta.47",
"@babel/plugin-transform-react-jsx": "7.0.0-beta.47",
"@babel/plugin-transform-react-jsx-self": "7.0.0-beta.47",
Expand Down
2 changes: 0 additions & 2 deletions packages/babel-preset-react/src/index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { declare } from "@babel/helper-plugin-utils";
import transformReactJSX from "@babel/plugin-transform-react-jsx";
import transformSyntaxJSX from "@babel/plugin-syntax-jsx";
import transformReactDisplayName from "@babel/plugin-transform-react-display-name";
import transformReactJSXSource from "@babel/plugin-transform-react-jsx-source";
import transformReactJSXSelf from "@babel/plugin-transform-react-jsx-self";
Expand All @@ -27,7 +26,6 @@ export default declare((api, opts) => {
transformReactJSX,
{ pragma, pragmaFrag, throwIfNamespace, useBuiltIns },
],
transformSyntaxJSX,
transformReactDisplayName,

development && transformReactJSXSource,
Expand Down
3 changes: 2 additions & 1 deletion packages/babel-preset-typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"@babel/core": "7.0.0-beta.47"
},
"devDependencies": {
"@babel/core": "7.0.0-beta.47"
"@babel/core": "7.0.0-beta.47",
"@babel/helper-plugin-test-runner": "7.0.0-beta.47"
}
}
44 changes: 38 additions & 6 deletions packages/babel-preset-typescript/src/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,42 @@
import { declare } from "@babel/helper-plugin-utils";
import transformTypeScript from "@babel/plugin-transform-typescript";

export default declare((api, { jsxPragma }) => {
api.assertVersion(7);
export default declare(
(api, { jsxPragma, allExtensions = false, isTSX = false }) => {
api.assertVersion(7);

return {
plugins: [[transformTypeScript, { jsxPragma }]],
};
});
if (typeof allExtensions !== "boolean") {
throw new Error(".allExtensions must be a boolean, or undefined");
}
if (typeof isTSX !== "boolean") {
throw new Error(".allExtensions must be a boolean, or undefined");

This comment has been minimized.

Copy link
@TrejGun

TrejGun May 23, 2018

isTSX must be a boolean, or undefined

This comment has been minimized.

Copy link
@loganfsmyth

loganfsmyth May 23, 2018

Author Member

@TrejGun Thanks! Might be better to comment on the PR in the future, since it's a lot easier to miss comments on merge commits.

}

if (isTSX && !allExtensions) {
throw new Error("isTSX:true requires allExtensions:true");
}

return {
overrides: allExtensions
? [
{
plugins: [[transformTypeScript, { jsxPragma, isTSX }]],
},
]
: [
{
// Only set 'test' if explicitly requested, since it requires that
// Babel is being called`
test: /\.ts$/,
plugins: [[transformTypeScript, { jsxPragma }]],
},
{
// Only set 'test' if explicitly requested, since it requires that
// Babel is being called`
test: /\.tsx$/,
plugins: [[transformTypeScript, { jsxPragma, isTSX: true }]],
},
],
};
},
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum Example {
Value
}

foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"presets": [
["flow", {}, "before"],
"typescript",
["flow", {}, "after"]
],
"throws": "enum is a reserved word (1:0)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type Foo = {||};

foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"presets": [
["flow", {}, "before"],
"typescript",
["flow", {}, "after"]
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type Foo = {||};

foo;
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"presets": [
["flow", {}, "before"],
"typescript",
["flow", {}, "after"]
],
"throws": "Unexpected token (1:12)"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
enum Example {
Value
}

foo;
Loading

0 comments on commit eb3334a

Please sign in to comment.