flow-upgrade 1.0.4 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/README.md +14 -2
  2. package/dist/Styled.js +12 -14
  3. package/dist/Types.js +21 -1
  4. package/dist/bin/runSpecificCodemod.js +117 -0
  5. package/dist/bin/upgrade.js +75 -0
  6. package/dist/codemodUtils/getClassMemberName.js +27 -0
  7. package/dist/codemodUtils/replaceMethodWithArrowProp.js +60 -0
  8. package/dist/codemods/collapseObjectInitialization.js +250 -0
  9. package/dist/codemods/convertImplicitInexactObjectTypes.js +35 -0
  10. package/dist/codemods/removeAnnotationsInDestructuring.js +40 -0
  11. package/dist/codemods/removeDuplicateClassProperties.js +268 -0
  12. package/dist/findFlowFiles.js +136 -156
  13. package/dist/runCodemods.js +36 -0
  14. package/dist/upgrade.js +127 -150
  15. package/dist/upgrades/0.170.0/index.js +25 -0
  16. package/dist/upgrades/0.176.0/index.js +25 -0
  17. package/dist/upgrades/0.84.0/index.js +25 -0
  18. package/dist/upgrades/index.js +29 -0
  19. package/dist/utils/redirectConsole.js +59 -0
  20. package/package.json +36 -20
  21. package/dist/codemods/ReactUtils.js +0 -140
  22. package/dist/codemods/createAggregateCodemod.js +0 -36
  23. package/dist/codemods/runCodemods.js +0 -53
  24. package/dist/index.js +0 -26
  25. package/dist/upgrades/0.53.0/ReactComponentExplicitTypeArgs/codemod.js +0 -154
  26. package/dist/upgrades/0.53.0/ReactComponentExplicitTypeArgs/index.js +0 -75
  27. package/dist/upgrades/0.53.0/ReactComponentSimplifyTypeArgs/codemod.js +0 -65
  28. package/dist/upgrades/0.53.0/ReactComponentSimplifyTypeArgs/index.js +0 -52
  29. package/dist/upgrades/0.53.0/ReactUtilityTypes/codemod.js +0 -200
  30. package/dist/upgrades/0.53.0/ReactUtilityTypes/index.js +0 -59
@@ -1,200 +0,0 @@
1
- /**
2
- * @format
3
- */
4
-
5
- 'use strict';
6
-
7
- // All the event names that we need to add <> to.
8
-
9
- const SYNTHETIC_EVENT_NAMES = new Set(['SyntheticEvent', 'SyntheticAnimationEvent', 'SyntheticClipboardEvent', 'SyntheticCompositionEvent', 'SyntheticInputEvent', 'SyntheticUIEvent', 'SyntheticFocusEvent', 'SyntheticKeyboardEvent', 'SyntheticMouseEvent', 'SyntheticDragEvent', 'SyntheticWheelEvent', 'SyntheticTouchEvent', 'SyntheticTransitionEvent']);
10
-
11
- /**
12
- * This codemod alters, removes, and replaces various React utilities that
13
- * had API changes when upgrading to this version. This includes the following
14
- * list:
15
- *
16
- * - `React$Node`.
17
- * - `React$Element`.
18
- * - `ReactClass`.
19
- * - `ReactComponent`.
20
- * - The return type of React component render.
21
- */
22
- module.exports = (j, root) => {
23
- const recast = require('recast');
24
- const ReactUtils = require('../../../codemods/ReactUtils')(j);
25
- const reactName = ReactUtils.getImportedReactName(root);
26
- const componentPattern = ReactUtils.getImportedComponentClassPattern(root);
27
- const hasElement = ReactUtils.hasDestructuredElement(root, reactName);
28
-
29
- // There is a bug in recast so we can't use `root.find()`. Instead we need to
30
- // visit with recast manually so we can visit the nodes it misses.
31
- root.paths().forEach(path => {
32
- recast.visit(path, {
33
- // Here is where we do all of our transformations.
34
- visitGenericTypeAnnotation: visitGenericTypeAnnotation,
35
-
36
- // We want to replace default React imports with a namespace import.
37
- visitImportDeclaration: visitImportDeclaration,
38
-
39
- // recast has a bug where it won't visit `superTypeParameters` on class
40
- // declarations and expressions. Fix that here.
41
- visitClassDeclaration: visitClass,
42
- visitClassExpression: visitClass
43
- });
44
- });
45
-
46
- function visitClass(path) {
47
- // Continue traversing the path. This is the default behavior.
48
- this.traverse(path);
49
- // There is a bug in recast which means we end up not traversing
50
- // `superTypeParameters`! So handle that that bug by visiting
51
- // `superTypeParameters` here.
52
- this.visitWithoutReset(path.get('superTypeParameters'));
53
- }
54
-
55
- function visitImportDeclaration(path) {
56
- const node = path.node;
57
-
58
- // import React from 'react'; ==> import * as React from 'react';
59
- if (node.importKind === 'value' && node.source && node.source.type === 'Literal' && node.source.value === 'react' && node.specifiers.length === 1 && node.specifiers[0].type === 'ImportDefaultSpecifier') {
60
- node.specifiers[0] = j.importNamespaceSpecifier(node.specifiers[0].local);
61
- }
62
-
63
- // Continue traversal if we do not want to apply a transformation to
64
- // this node.
65
- this.traverse(path);
66
- }
67
-
68
- function visitGenericTypeAnnotation(path) {
69
- const node = path.node;
70
-
71
- // React$Node<any> ==> React.Node
72
- if (node.id.type === 'Identifier' && (node.id.name === 'React$Node' || node.id.name === 'ReactNode')) {
73
- // React.Node no longer has type parameters.
74
- node.typeParameters = null;
75
- // Use the exported type from the React module. If it does not exist then
76
- // use React$Node.
77
- node.id = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Node')) : j.identifier('React$Node');
78
- // We have handled this node. No need to continue traversing.
79
- return false;
80
- }
81
-
82
- // React$Element<Config> ==> React.Element<React.ComponentType<Props>>
83
- if (
84
- // React$Element or ReactElement
85
- node.id.type === 'Identifier' && (node.id.name === 'React$Element' || node.id.name === 'ReactElement') ||
86
- // React.Element
87
- node.id.type === 'QualifiedTypeIdentifier' && node.id.qualification && node.id.qualification.type === 'Identifier' && node.id.qualification.name === reactName && node.id.id && node.id.id.type === 'Identifier' && node.id.id.name === 'Element' ||
88
- // const {Element} = React;
89
- // Element
90
- hasElement && node.id.type === 'Identifier' && node.id.name === 'Element') {
91
- // If we have no type parameters then add an empty type parameter
92
- // instantiation.
93
- if (!node.typeParameters) {
94
- node.typeParameters = j.typeParameterInstantiation([]);
95
- }
96
- // If we have a first type parameter...
97
- if (node.typeParameters.params[0]) {
98
- const firstTypeParam = node.typeParameters.params[0];
99
- // ...and that type parameter is not `any`, `mixed`, or `*`...
100
- if (firstTypeParam && firstTypeParam.type !== 'AnyTypeAnnotation' && firstTypeParam.type !== 'ExistsTypeAnnotation') {
101
- // ...then wrap the type parameter with `React.ComponentType<Props>`.
102
- node.typeParameters.params[0] = j.genericTypeAnnotation(
103
- // Get the `React.ComponentType` type name, or use the global.
104
- reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('ComponentType')) : j.identifier('React$ComponentType'),
105
- // Put the type param we are wrapping as the first and only
106
- // type argument.
107
- j.typeParameterInstantiation([firstTypeParam]));
108
- }
109
- }
110
- // If we do not have a first type parameter, or our type parameter is `*`
111
- // then we want to use `any` instead. This is because using `*` will often
112
- // cause errors that are unrelated to whether or not the code is correct.
113
- // Almost all of the time when a user writes `React.Element<*>` they meant
114
- // `React.Element<any>`. They just felt bad about writing `any`.
115
- if (node.typeParameters.params.length === 0 || node.typeParameters.params[0].type === 'ExistsTypeAnnotation') {
116
- node.typeParameters = j.typeParameterInstantiation([j.anyTypeAnnotation()]);
117
- }
118
- // Update the type identifier to be `React.Element` or the
119
- // equivalent global.
120
- node.id = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Element')) : j.identifier('React$Element');
121
- // We have handled this node. No need to continue traversing.
122
- return false;
123
- }
124
-
125
- // ReactClass<Config> ==> React.ComponentType<Props>
126
- if (node.id.type === 'Identifier' && node.id.name === 'ReactClass' && node.typeParameters && node.typeParameters.type === 'TypeParameterInstantiation') {
127
- // Replace ReactClass with the new type.
128
- return j.genericTypeAnnotation(
129
- // Get the component type name. Either as a qualified name from our
130
- // React import or using the global.
131
- reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('ComponentType')) : j.identifier('React$ComponentType'),
132
- // Keep the type parameters we had previously.
133
- node.typeParameters);
134
- }
135
-
136
- // React$Component<Defaults, Props, State> ==> React.Component<Props, State>
137
- if ((node.id.type === 'Identifier' && (node.id.name === 'ReactComponent' || node.id.name === 'React$Component') || componentPattern && componentPattern(node.id)) && node.typeParameters && node.typeParameters.type === 'TypeParameterInstantiation') {
138
- // Remove the default props type argument.
139
- if (node.typeParameters.params.length >= 3) {
140
- node.typeParameters.params.shift();
141
- }
142
- // If the user has destructured React and used Component or PureComponent
143
- // directly then we should not update the identifier of this node.
144
- if (node.id.type === 'Identifier' && (node.id.name === 'Component' || node.id.name === 'PureComponent')) {
145
- return false;
146
- }
147
- // Replace the identifier with React.Component
148
- node.id = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Component')) : j.identifier('React$Component');
149
- // We have handled this node. No need to continue traversing.
150
- return false;
151
- }
152
-
153
- // SyntheticEvent ==> SyntheticEvent<>
154
- if (node.id.type === 'Identifier' && SYNTHETIC_EVENT_NAMES.has(node.id.name)) {
155
- node.typeParameters = j.typeParameterInstantiation([]);
156
- return false;
157
- }
158
-
159
- // Continue traversal if we do not want to apply a transformation to
160
- // this node.
161
- this.traverse(path);
162
- }
163
-
164
- // render(): React.Element<any> ==> render(): React.Node
165
- if (componentPattern) {
166
- root.find(j.ClassDeclaration, {
167
- superClass: componentPattern,
168
- body: { type: 'ClassBody' }
169
- }).forEach(handleReactClassPath);
170
-
171
- root.find(j.ClassExpression, {
172
- superClass: componentPattern,
173
- body: { type: 'ClassBody' }
174
- }).forEach(handleReactClassPath);
175
- }
176
-
177
- function handleReactClassPath(path) {
178
- // For every member in the class's body...
179
- path.node.body.body.forEach(method => {
180
- // If this member is the component's render method and it has a
181
- // return type...
182
- if (method.type === 'MethodDefinition' && method.key && method.key.type === 'Identifier' && method.key.name === 'render' && method.value && method.value.type === 'FunctionExpression' && method.value.returnType && method.value.returnType.type === 'TypeAnnotation') {
183
- const returnType = method.value.returnType;
184
- // If this is a return type from render that people commonly use then
185
- // replace it with the new recommendation. React.Node
186
- if (isRenderReturnReactElement(returnType.typeAnnotation) || returnType.typeAnnotation.type === 'NullableTypeAnnotation' && isRenderReturnReactElement(returnType.typeAnnotation.typeAnnotation)) {
187
- returnType.typeAnnotation = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Node')) : j.identifier('React$Node');
188
- }
189
- }
190
- });
191
- }
192
-
193
- function isRenderReturnReactElement(node) {
194
- // Is the node React.Element<any>, React.Element<mixed>,
195
- // or React.Element<*>?
196
- return reactName && node && node.type === 'GenericTypeAnnotation' && node.id.type === 'QualifiedTypeIdentifier' && node.id.qualification.type === 'Identifier' && node.id.qualification.name === reactName && node.id.id.type === 'Identifier' && node.id.id.name === 'Element' && node.typeParameters && node.typeParameters.type === 'TypeParameterInstantiation' && (node.typeParameters.params.length === 0 || node.typeParameters.params[0] && (node.typeParameters.params[0].type === 'AnyTypeAnnotation' || node.typeParameters.params[0].type === 'ExistsTypeAnnotation'));
197
- }
198
-
199
- return true;
200
- };
@@ -1,59 +0,0 @@
1
- 'use strict';
2
-
3
- /**
4
- * @format
5
- *
6
- */
7
-
8
- const path = require('path');
9
- const Styled = require('../../../Styled');
10
-
11
- exports.kind = 'codemod';
12
-
13
- exports.title = 'Remove and replace old React utility types.';
14
-
15
- exports.description = `
16
- In the past Flow has some very confusing and inconvenient utility types for
17
- React. We removed these utility types and replaced them with types which should
18
- make a lot more sense. These types will make it a lot easier to effectively type
19
- advanced React features like higher order components.
20
-
21
- Some of the most powerful new utility types can be seen in the following
22
- example:
23
-
24
- ${Styled.codeblock(`
25
- import * as React from 'react';
26
-
27
- function MyComponent(props: Props): React.Node {
28
- /* ... */
29
- }
30
- (React.createElement(MyComponent): React.Element<typeof MyComponent>);
31
-
32
- class MyStatefulComponent extends React.Component<Props> {
33
- /* ... */
34
- }
35
- (React.createElement(MyComponent): React.Element<typeof MyStatefulComponent>);
36
-
37
- function myHOC(
38
- Component: React.ComponentType<Props>,
39
- ): React.ComponentType<NewProps> {
40
- return class extends React.Component<NewProps> {
41
- /* ... */
42
- };
43
- }`.slice(1))}
44
-
45
- ${Styled.list([`React.Node is the new return type for render methods. This codemod will
46
- replace any render methods that return the type ?React.Element<any> with
47
- React.Node.`, `React.Element<Component> now takes the type of a component as its type
48
- argument instead of the type of a the component's props as it used to. This
49
- codemod will upgrade everywhere you use React.Element<Props> to
50
- React.Element<React.ComponentType<Props>>.`, `Speaking of React.ComponentType<Props>, this is a new utility type which
51
- represents either a class component, or a stateless functional component. This
52
- type is very useful when you want to type higher order components. We will
53
- replace everywhere you use ReactClass<Props> in your codebase with
54
- React.ComponentType<Props>. (ReactClass<Props> was very buggy and so this may
55
- cause a lot of new errors!)`, `Also note that we used import * as React from 'react'. You must use the
56
- import * syntax if you want to use the new utility types. This codemod will
57
- update your code to use this new style of import.`])}`.slice(1);
58
-
59
- exports.transformPath = path.join(__dirname, './codemod.js');