Skip to content

Commit

Permalink
fix: replace existing propTypes when removeExistingPropTypes (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
eps1lon authored Apr 3, 2020
1 parent d514399 commit 3166104
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 23 deletions.
30 changes: 15 additions & 15 deletions src/injector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ function plugin(
let importName = '';
let needImport = false;
let alreadyImported = false;
let originalPropTypesPath: null | babel.NodePath = null;

return {
visitor: {
Expand All @@ -121,19 +122,17 @@ function plugin(
importName = 'PropTypes';
}

if (removeExistingPropTypes) {
path.get('body').forEach((nodePath) => {
const { node } = nodePath;
if (
babelTypes.isExpressionStatement(node) &&
babelTypes.isAssignmentExpression(node.expression, { operator: '=' }) &&
babelTypes.isMemberExpression(node.expression.left) &&
babelTypes.isIdentifier(node.expression.left.property, { name: 'propTypes' })
) {
nodePath.remove();
}
});
}
path.get('body').forEach((nodePath) => {
const { node } = nodePath;
if (
babelTypes.isExpressionStatement(node) &&
babelTypes.isAssignmentExpression(node.expression, { operator: '=' }) &&
babelTypes.isMemberExpression(node.expression.left) &&
babelTypes.isIdentifier(node.expression.left.property, { name: 'propTypes' })
) {
originalPropTypesPath = nodePath;
}
});
},
exit(path) {
if (alreadyImported || !needImport) return;
Expand Down Expand Up @@ -280,8 +279,9 @@ function plugin(

mapOfPropTypes.set(placeholder, source);

// Insert prop types
if (babelTypes.isExportNamedDeclaration(path.parent)) {
if (removeExistingPropTypes && originalPropTypesPath !== null) {
originalPropTypesPath.replaceWith(babel.template.ast(placeholder) as babelTypes.Statement);
} else if (babelTypes.isExportNamedDeclaration(path.parent)) {
path.insertAfter(babel.template.ast(`export { ${nodeName} };`));
path.insertAfter(babel.template.ast(placeholder));
path.parentPath.replaceWith(path.node);
Expand Down
7 changes: 7 additions & 0 deletions test/code-order/input.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import * as React from 'react';

export interface Props {
value: unknown;
}

export default function Component(props: Props): JSX.Element;
15 changes: 15 additions & 0 deletions test/code-order/input.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types';

function Component(props) {
const { value } = props;
return <div>{value}</div>;
}

const someValidator = () => new Error();

Component.propTypes = {
value: PropTypes.any,
};

export default Component;
9 changes: 9 additions & 0 deletions test/code-order/options.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { TestOptions } from '../types';

const options: TestOptions = {
injector: {
removeExistingPropTypes: true,
},
};

export default options;
15 changes: 15 additions & 0 deletions test/code-order/output.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import React from 'react';
import PropTypes from 'prop-types';

function Component(props) {
const { value } = props;
return <div>{value}</div>;
}

const someValidator = () => new Error();

Component.propTypes = {
value: PropTypes.any.isRequired,
};

export default Component;
10 changes: 10 additions & 0 deletions test/code-order/output.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"type": "ProgramNode",
"body": [
{
"type": "ComponentNode",
"name": "Component",
"types": [{ "type": "PropTypeNode", "name": "value", "propType": { "type": "AnyNode" } }]
}
]
}
24 changes: 16 additions & 8 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ for (const testCase of testCases) {
const astPath = path.join(dirname, 'output.json');
const outputPath = path.join(dirname, 'output.js');
const optionsPath = path.join(dirname, 'options.ts');
const inputJS = path.join(dirname, 'input.js');

it(testName, () => {
const options: TestOptions = fs.existsSync(optionsPath) ? require(optionsPath).default : {};
Expand All @@ -42,21 +43,28 @@ for (const testCase of testCases) {
}
//#endregion

let result = '';
// For d.ts files we just generate the AST
let inputSource = null;
if (testCase.endsWith('.d.ts')) {
result = ttp.generate(ast, options.generator);
}
// For .tsx? files we transpile them and inject the proptypes
else {
const transpiled = ttp.ts.transpileModule(fs.readFileSync(testCase, 'utf8'), {
try {
inputSource = fs.readFileSync(inputJS, { encoding: 'utf8' });
} catch (error) {}
} else {
inputSource = ttp.ts.transpileModule(fs.readFileSync(testCase, 'utf8'), {
compilerOptions: {
target: ttp.ts.ScriptTarget.ESNext,
jsx: ttp.ts.JsxEmit.Preserve,
},
}).outputText;
}

const injected = ttp.inject(ast, transpiled, options.injector);
let result = '';
// For d.ts files we just generate the AST
if (!inputSource) {
result = ttp.generate(ast, options.generator);
}
// For .tsx? files we transpile them and inject the proptypes
else {
const injected = ttp.inject(ast, inputSource, options.injector);
if (!injected) {
throw new Error('Injection failed');
}
Expand Down

0 comments on commit 3166104

Please sign in to comment.