Merge pull request #7955 from loganfsmyth/typescript-filename-required
Verify that files are .ts/.tsx before treating as Typescript files.
This commit is contained in:
commit
eb3334a14e
@ -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 = {
|
||||
@ -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">,
|
||||
>),
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import assert from "assert";
|
||||
import cloneDeep from "lodash/cloneDeep";
|
||||
import trimEnd from "lodash/trimEnd";
|
||||
import resolve from "try-resolve";
|
||||
@ -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 = [];
|
||||
|
||||
@ -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";
|
||||
const actualLoc = findFile(taskDir + "/input");
|
||||
const expectLoc = findFile(taskDir + "/output", true /* allowJSON */);
|
||||
let execLoc = findFile(taskDir + "/exec");
|
||||
|
||||
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`);
|
||||
|
||||
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");
|
||||
@ -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"));
|
||||
|
||||
@ -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.",
|
||||
);
|
||||
}
|
||||
|
||||
@ -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 }]);
|
||||
},
|
||||
};
|
||||
|
||||
@ -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");
|
||||
},
|
||||
};
|
||||
|
||||
@ -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");
|
||||
}
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"plugins": ["syntax-jsx", ["transform-typescript", { "jsxPragma": "h" }]]
|
||||
"plugins": [["transform-typescript", { "jsxPragma": "h", "isTSX": true }]]
|
||||
}
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"plugins": ["syntax-jsx", "transform-typescript"]
|
||||
"plugins": [["transform-typescript", { "isTSX": true }]]
|
||||
}
|
||||
|
||||
@ -1,3 +1,3 @@
|
||||
{
|
||||
"plugins": ["syntax-jsx", "transform-typescript"]
|
||||
"plugins": [["transform-typescript", { "isTSX": true }]]
|
||||
}
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -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";
|
||||
@ -27,7 +26,6 @@ export default declare((api, opts) => {
|
||||
transformReactJSX,
|
||||
{ pragma, pragmaFrag, throwIfNamespace, useBuiltIns },
|
||||
],
|
||||
transformSyntaxJSX,
|
||||
transformReactDisplayName,
|
||||
|
||||
development && transformReactJSXSource,
|
||||
|
||||
@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
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 }]],
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
5
packages/babel-preset-typescript/test/fixtures/flow-compat/js-invalid/input.js
vendored
Normal file
5
packages/babel-preset-typescript/test/fixtures/flow-compat/js-invalid/input.js
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
enum Example {
|
||||
Value
|
||||
}
|
||||
|
||||
foo;
|
||||
8
packages/babel-preset-typescript/test/fixtures/flow-compat/js-invalid/options.json
vendored
Normal file
8
packages/babel-preset-typescript/test/fixtures/flow-compat/js-invalid/options.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
["flow", {}, "before"],
|
||||
"typescript",
|
||||
["flow", {}, "after"]
|
||||
],
|
||||
"throws": "enum is a reserved word (1:0)"
|
||||
}
|
||||
3
packages/babel-preset-typescript/test/fixtures/flow-compat/js-valid/input.js
vendored
Normal file
3
packages/babel-preset-typescript/test/fixtures/flow-compat/js-valid/input.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
type Foo = {||};
|
||||
|
||||
foo;
|
||||
1
packages/babel-preset-typescript/test/fixtures/flow-compat/js-valid/output.js
vendored
Normal file
1
packages/babel-preset-typescript/test/fixtures/flow-compat/js-valid/output.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
foo;
|
||||
7
packages/babel-preset-typescript/test/fixtures/flow-compat/options.json
vendored
Normal file
7
packages/babel-preset-typescript/test/fixtures/flow-compat/options.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"presets": [
|
||||
["flow", {}, "before"],
|
||||
"typescript",
|
||||
["flow", {}, "after"]
|
||||
]
|
||||
}
|
||||
3
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-invalid/input.ts
vendored
Normal file
3
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-invalid/input.ts
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
type Foo = {||};
|
||||
|
||||
foo;
|
||||
8
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-invalid/options.json
vendored
Normal file
8
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-invalid/options.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
["flow", {}, "before"],
|
||||
"typescript",
|
||||
["flow", {}, "after"]
|
||||
],
|
||||
"throws": "Unexpected token (1:12)"
|
||||
}
|
||||
5
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-valid/input.ts
vendored
Normal file
5
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-valid/input.ts
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
enum Example {
|
||||
Value
|
||||
}
|
||||
|
||||
foo;
|
||||
7
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-valid/output.js
vendored
Normal file
7
packages/babel-preset-typescript/test/fixtures/flow-compat/ts-valid/output.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
var Example;
|
||||
|
||||
(function (Example) {
|
||||
Example[Example["Value"] = 0] = "Value";
|
||||
})(Example || (Example = {}));
|
||||
|
||||
foo;
|
||||
3
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-invalid/input.tsx
vendored
Normal file
3
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-invalid/input.tsx
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
type Foo = {||};
|
||||
|
||||
foo;
|
||||
8
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-invalid/options.json
vendored
Normal file
8
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-invalid/options.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
["flow", {}, "before"],
|
||||
"typescript",
|
||||
["flow", {}, "after"]
|
||||
],
|
||||
"throws": "Unexpected token (1:12)"
|
||||
}
|
||||
5
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-valid/input.tsx
vendored
Normal file
5
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-valid/input.tsx
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
enum Example {
|
||||
Value
|
||||
}
|
||||
|
||||
foo;
|
||||
7
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-valid/output.js
vendored
Normal file
7
packages/babel-preset-typescript/test/fixtures/flow-compat/tsx-valid/output.js
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
var Example;
|
||||
|
||||
(function (Example) {
|
||||
Example[Example["Value"] = 0] = "Value";
|
||||
})(Example || (Example = {}));
|
||||
|
||||
foo;
|
||||
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/js-valid/input.js
vendored
Normal file
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/js-valid/input.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
(<div />);
|
||||
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/js-valid/output.js
vendored
Normal file
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/js-valid/output.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
React.createElement("div", null);
|
||||
7
packages/babel-preset-typescript/test/fixtures/jsx-compat/options.json
vendored
Normal file
7
packages/babel-preset-typescript/test/fixtures/jsx-compat/options.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"presets": [
|
||||
["react", {}, "before"],
|
||||
"typescript",
|
||||
["react", {}, "after"]
|
||||
]
|
||||
}
|
||||
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/ts-invalid/input.ts
vendored
Normal file
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/ts-invalid/input.ts
vendored
Normal file
@ -0,0 +1 @@
|
||||
(<div />);
|
||||
8
packages/babel-preset-typescript/test/fixtures/jsx-compat/ts-invalid/options.json
vendored
Normal file
8
packages/babel-preset-typescript/test/fixtures/jsx-compat/ts-invalid/options.json
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"presets": [
|
||||
["react", {}, "before"],
|
||||
"typescript",
|
||||
["react", {}, "after"]
|
||||
],
|
||||
"throws": "Unexpected token, expected \"</>\" (1:6)"
|
||||
}
|
||||
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/tsx-valid/input.tsx
vendored
Normal file
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/tsx-valid/input.tsx
vendored
Normal file
@ -0,0 +1 @@
|
||||
(<div />);
|
||||
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/tsx-valid/output.js
vendored
Normal file
1
packages/babel-preset-typescript/test/fixtures/jsx-compat/tsx-valid/output.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
React.createElement("div", null);
|
||||
3
packages/babel-preset-typescript/test/index.js
Normal file
3
packages/babel-preset-typescript/test/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import runner from "@babel/helper-plugin-test-runner";
|
||||
|
||||
runner(__dirname);
|
||||
@ -23,7 +23,7 @@
|
||||
});
|
||||
it("handles the typescript preset", () => {
|
||||
const output = Babel.transform("var a: string;", {
|
||||
presets: ["typescript"],
|
||||
presets: [["typescript", { allExtensions: true }]],
|
||||
}).code;
|
||||
expect(output).toBe("var a;");
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user