Repository: brigand/babel-plugin-flow-react-proptypes
Pull request #107 (2017-06-10 07:29:21)

Mark exported types as required
This worked for anything object-ish (shape, raw, runtime-merge), but not for strings etc.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/11914289/badge)](https://coveralls.io/builds/11914289)

Coverage increased (+0.01%) to 93.189% when pulling **1cd1009d34b4cc6acbbc50cac0a685223693acf4 on mhaas:mark-exported-types-as-required** into **d00c85cfdc667735c39b5bd10244377c3425de98 on brigand:master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/11914297/badge)](https://coveralls.io/builds/11914297)

Coverage increased (+0.01%) to 93.189% when pulling **1cd1009d34b4cc6acbbc50cac0a685223693acf4 on mhaas:mark-exported-types-as-required** into **d00c85cfdc667735c39b5bd10244377c3425de98 on brigand:master**.


Patch:
diff --git a/src/makePropTypesAst.js b/src/makePropTypesAst.js
index c145d43..42f3501 100644
--- a/src/makePropTypesAst.js
+++ b/src/makePropTypesAst.js
@@ -48,6 +48,7 @@ export function makePropTypesAstForPropTypesAssignment(propTypeData) {
 export function makePropTypesAstForExport(propTypeData) {
   let ast = makePropTypesAstForPropTypesAssignment(propTypeData);
   if (ast == null) {
+    propTypeData.isRequired = !propTypeData.optional;
     ast = makePropType(propTypeData);
   }
   return ast;
@@ -196,7 +197,7 @@ function processQualifiedTypeIdentifierIntoMemberExpression(qualifiedTypeIdentif
 
   const memberExpression = t.memberExpression(objectAST, propertyAST);
 
-  return t.conditionalExpression(makeNullCheckAST(memberExpression), t.objectExpression([]), memberExpression)
+  return t.conditionalExpression(makeNullCheckAST(memberExpression), t.objectExpression([]), memberExpression);
 
 }
 


Test patch:
diff --git a/src/__tests__/__snapshots__/export-non-object-types-test.js.snap b/src/__tests__/__snapshots__/export-non-object-types-test.js.snap
index 6fbcde0..be32f87 100644
--- a/src/__tests__/__snapshots__/export-non-object-types-test.js.snap
+++ b/src/__tests__/__snapshots__/export-non-object-types-test.js.snap
@@ -2,6 +2,6 @@ exports[`test export-non-object-types 1`] = `
 "\"use strict\";
 
 if (typeof exports !== \"undefined\") Object.defineProperty(exports, \"babelPluginFlowReactPropTypes_proptype_Answer\", {
-  value: require(\"prop-types\").oneOf([\"Yes\", \"No\"])
+  value: require(\"prop-types\").oneOf([\"Yes\", \"No\"]).isRequired
 });"
 `;
diff --git a/src/__tests__/__snapshots__/export-string-type.js.snap b/src/__tests__/__snapshots__/export-string-type.js.snap
new file mode 100644
index 0000000..ea6b1e6
--- /dev/null
+++ b/src/__tests__/__snapshots__/export-string-type.js.snap
@@ -0,0 +1,10 @@
+exports[`test export-intersection-type 1`] = `
+"\"use strict\";
+
+if (typeof exports !== \"undefined\") Object.defineProperty(exports, \"babelPluginFlowReactPropTypes_proptype_T\", {
+  value: require(\"prop-types\").string.isRequired
+});
+if (typeof exports !== \"undefined\") Object.defineProperty(exports, \"babelPluginFlowReactPropTypes_proptype_TOptional\", {
+  value: require(\"prop-types\").string
+});"
+`;
diff --git a/src/__tests__/__snapshots__/export-union-type.js.snap b/src/__tests__/__snapshots__/export-union-type.js.snap
index 4586190..06ff6f3 100644
--- a/src/__tests__/__snapshots__/export-union-type.js.snap
+++ b/src/__tests__/__snapshots__/export-union-type.js.snap
@@ -2,6 +2,6 @@ exports[`test export-union-type 1`] = `
 "\"use strict\";
 
 if (typeof exports !== \"undefined\") Object.defineProperty(exports, \"babelPluginFlowReactPropTypes_proptype_A\", {
-  value: require(\"prop-types\").oneOf([\"option1\", \"option2\"])
+  value: require(\"prop-types\").oneOf([\"option1\", \"option2\"]).isRequired
 });"
 `;
diff --git a/src/__tests__/__snapshots__/instance-of-object-properties.js.snap b/src/__tests__/__snapshots__/instance-of-object-properties.js.snap
index d5f0f1c..fc774ee 100644
--- a/src/__tests__/__snapshots__/instance-of-object-properties.js.snap
+++ b/src/__tests__/__snapshots__/instance-of-object-properties.js.snap
@@ -10,10 +10,10 @@ function _possibleConstructorReturn(self, call) { if (!self) { throw new Referen
 function _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
 
 if (typeof exports !== \'undefined\') Object.defineProperty(exports, \'babelPluginFlowReactPropTypes_proptype_Fact\', {
-  value: typeof (Foo.Bar == null ? {} : Foo.Bar) === \'function\' ? require(\'prop-types\').instanceOf(Foo.Bar == null ? {} : Foo.Bar) : require(\'prop-types\').any
+  value: typeof (Foo.Bar == null ? {} : Foo.Bar) === \'function\' ? require(\'prop-types\').instanceOf(Foo.Bar == null ? {} : Foo.Bar).isRequired : require(\'prop-types\').any.isRequired
 });
 if (typeof exports !== \'undefined\') Object.defineProperty(exports, \'babelPluginFlowReactPropTypes_proptype_FactMap\', {
-  value: typeof (Foo.Map == null ? {} : Foo.Map) === \'function\' ? require(\'prop-types\').instanceOf(Foo.Map == null ? {} : Foo.Map) : require(\'prop-types\').any
+  value: typeof (Foo.Map == null ? {} : Foo.Map) === \'function\' ? require(\'prop-types\').instanceOf(Foo.Map == null ? {} : Foo.Map).isRequired : require(\'prop-types\').any.isRequired
 });
 
 var MyComponent = function (_React$Component) {
diff --git a/src/__tests__/__snapshots__/render-imported-non-shape-types-generate-warnings.js.snap b/src/__tests__/__snapshots__/render-imported-non-shape-types-generate-warnings.js.snap
index 81a7b3c..3c60d68 100644
--- a/src/__tests__/__snapshots__/render-imported-non-shape-types-generate-warnings.js.snap
+++ b/src/__tests__/__snapshots__/render-imported-non-shape-types-generate-warnings.js.snap
@@ -17,4 +17,19 @@ Array [
 ]
 `;
 
-exports[`test imported-non-shape-generates-warnings: no props given 1`] = `Array []`;
+exports[`test imported-non-shape-generates-warnings: no props given 1`] = `
+Array [
+  Array [
+    "Warning: Failed prop type: The prop \`stringValue\` is marked as required in \`C\`, but its value is \`undefined\`.
+    in C",
+  ],
+  Array [
+    "Warning: Failed prop type: The prop \`numberValue\` is marked as required in \`C\`, but its value is \`undefined\`.
+    in C",
+  ],
+  Array [
+    "Warning: Failed prop type: The prop \`enumStringValue\` is marked as required in \`C\`, but its value is \`undefined\`.
+    in C",
+  ],
+]
+`;
diff --git a/src/__tests__/__snapshots__/union-types-and-contants.js.snap b/src/__tests__/__snapshots__/union-types-and-contants.js.snap
index 8da8b90..bd319a5 100644
--- a/src/__tests__/__snapshots__/union-types-and-contants.js.snap
+++ b/src/__tests__/__snapshots__/union-types-and-contants.js.snap
@@ -14,7 +14,7 @@ function _inherits(subClass, superClass) { if (typeof superClass !== \"function\
 var React = require(\'react\');
 
 if (typeof exports !== \'undefined\') Object.defineProperty(exports, \'babelPluginFlowReactPropTypes_proptype_U\', {
-  value: require(\'prop-types\').oneOfType([require(\'prop-types\').oneOf([\'foo\']), require(\'prop-types\').oneOf([\'bar\']), require(\'prop-types\').number])
+  value: require(\'prop-types\').oneOfType([require(\'prop-types\').oneOf([\'foo\']), require(\'prop-types\').oneOf([\'bar\']), require(\'prop-types\').number]).isRequired
 });
 
 var Foo = function (_React$Component) {
diff --git a/src/__tests__/export-string-type.js b/src/__tests__/export-string-type.js
new file mode 100644
index 0000000..ac3b0eb
--- /dev/null
+++ b/src/__tests__/export-string-type.js
@@ -0,0 +1,14 @@
+const babel = require('babel-core');
+const content = `
+export type T = string;
+export type TOptional = ?string;
+`;
+
+it('export-intersection-type', () => {
+  const res = babel.transform(content, {
+    babelrc: false,
+    presets: ['es2015', 'stage-1', 'react'],
+    plugins: ['syntax-flow', require('../')],
+  }).code;
+  expect(res).toMatchSnapshot();
+});
diff --git a/src/__tests__/render-imported-non-shape-types-generate-warnings.js b/src/__tests__/render-imported-non-shape-types-generate-warnings.js
index 127f562..a2e692a 100644
--- a/src/__tests__/render-imported-non-shape-types-generate-warnings.js
+++ b/src/__tests__/render-imported-non-shape-types-generate-warnings.js
@@ -15,20 +15,11 @@ class C extends React.Component {
     
     render() { return <div/> };
 }
-  const tree1 = renderer.create(
-    <C/>
-  );`;
+`;
 
 const utils = require('./lib/render-component');
 
-/*
- * This test pretty much showcases that non-object exports are not working.
- * We would expect different errors.
- *
- * The test is currently passing, but serves more as documentation of existing issues
- * than of correct behavior.
- */
-
+// TODO: this incorrectly generates no errors. The types are not marked as required!
 it('imported-non-shape-generates-warnings: no props given', () => {
   const path = require('path');
   const renderCall = 'renderer.create(<C/>);';
@@ -43,10 +34,6 @@ it('imported-non-shape-generates-warnings: no props given', () => {
 
 it('imported-non-shape-generates-warnings: incorrect types given', () => {
   const path = require('path');
-  // TODO: the message generated here is probably not useful - numberValue and enumStringValue
-  // are apparently invalid, because they are not of type object.
-  // Apparently, our fallback to 'any' (which we don't want here anyways)
-  // causes this odd behavior.
   const renderCall = 'renderer.create(<C stringValue={5} numberValue="string" enumStringValue="incorrect"/>);';
   const fullSource = content + renderCall;
   const errorsSeen = utils.getConsoleErrorsForComponent(fullSource, [