flow-upgrade 1.1.0 → 2.0.0
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.
- package/README.md +10 -0
- package/dist/Styled.js +12 -14
- package/dist/Types.js +21 -1
- package/dist/bin/runSpecificCodemod.js +117 -0
- package/dist/bin/upgrade.js +75 -0
- package/dist/codemodUtils/getClassMemberName.js +27 -0
- package/dist/codemodUtils/replaceMethodWithArrowProp.js +60 -0
- package/dist/codemods/collapseObjectInitialization.js +250 -0
- package/dist/codemods/convertImplicitInexactObjectTypes.js +35 -0
- package/dist/codemods/removeAnnotationsInDestructuring.js +40 -0
- package/dist/codemods/removeDuplicateClassProperties.js +268 -0
- package/dist/findFlowFiles.js +136 -158
- package/dist/runCodemods.js +36 -0
- package/dist/upgrade.js +127 -153
- package/dist/upgrades/0.170.0/index.js +25 -0
- package/dist/upgrades/0.176.0/index.js +25 -0
- package/dist/upgrades/0.84.0/index.js +25 -0
- package/dist/upgrades/index.js +29 -0
- package/dist/utils/redirectConsole.js +59 -0
- package/package.json +29 -21
- package/dist/codemods/ReactUtils.js +0 -140
- package/dist/codemods/createAggregateCodemod.js +0 -36
- package/dist/codemods/runCodemods.js +0 -54
- package/dist/index.js +0 -38
- package/dist/upgrades/0.53.0/ReactComponentExplicitTypeArgs/codemod.js +0 -154
- package/dist/upgrades/0.53.0/ReactComponentExplicitTypeArgs/index.js +0 -75
- package/dist/upgrades/0.53.0/ReactComponentSimplifyTypeArgs/codemod.js +0 -65
- package/dist/upgrades/0.53.0/ReactComponentSimplifyTypeArgs/index.js +0 -52
- package/dist/upgrades/0.53.0/ReactUtilityTypes/codemod.js +0 -156
- package/dist/upgrades/0.53.0/ReactUtilityTypes/index.js +0 -59
- package/dist/upgrades/0.84.0/ExplicitInexactObjectSyntax/codemod.js +0 -18
- package/dist/upgrades/0.84.0/ExplicitInexactObjectSyntax/index.js +0 -25
|
@@ -1,156 +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 ReactUtils = require('../../../codemods/ReactUtils')(j);
|
|
24
|
-
const reactName = ReactUtils.getImportedReactName(root);
|
|
25
|
-
const componentPattern = ReactUtils.getImportedComponentClassPattern(root);
|
|
26
|
-
const hasElement = ReactUtils.hasDestructuredElement(root, reactName);
|
|
27
|
-
|
|
28
|
-
root.find(j.GenericTypeAnnotation).forEach(visitGenericTypeAnnotation);
|
|
29
|
-
root.find(j.ImportDeclaration).forEach(visitImportDeclaration);
|
|
30
|
-
|
|
31
|
-
function visitImportDeclaration(path) {
|
|
32
|
-
const node = path.node;
|
|
33
|
-
|
|
34
|
-
// import React from 'react'; ==> import * as React from 'react';
|
|
35
|
-
if (node.importKind === 'value' && node.source && node.source.type === 'Literal' && node.source.value === 'react' && node.specifiers.length === 1 && node.specifiers[0].type === 'ImportDefaultSpecifier') {
|
|
36
|
-
node.specifiers[0] = j.importNamespaceSpecifier(node.specifiers[0].local);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
function visitGenericTypeAnnotation(path) {
|
|
41
|
-
const node = path.node;
|
|
42
|
-
|
|
43
|
-
// React$Node<any> ==> React.Node
|
|
44
|
-
if (node.id.type === 'Identifier' && (node.id.name === 'React$Node' || node.id.name === 'ReactNode')) {
|
|
45
|
-
// React.Node no longer has type parameters.
|
|
46
|
-
node.typeParameters = null;
|
|
47
|
-
// Use the exported type from the React module. If it does not exist then
|
|
48
|
-
// use React$Node.
|
|
49
|
-
node.id = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Node')) : j.identifier('React$Node');
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
// React$Element<Config> ==> React.Element<React.ComponentType<Props>>
|
|
53
|
-
else if (
|
|
54
|
-
// React$Element or ReactElement
|
|
55
|
-
node.id.type === 'Identifier' && (node.id.name === 'React$Element' || node.id.name === 'ReactElement') ||
|
|
56
|
-
// React.Element
|
|
57
|
-
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' ||
|
|
58
|
-
// const {Element} = React;
|
|
59
|
-
// Element
|
|
60
|
-
hasElement && node.id.type === 'Identifier' && node.id.name === 'Element') {
|
|
61
|
-
// If we have no type parameters then add an empty type parameter
|
|
62
|
-
// instantiation.
|
|
63
|
-
if (!node.typeParameters) {
|
|
64
|
-
node.typeParameters = j.typeParameterInstantiation([]);
|
|
65
|
-
}
|
|
66
|
-
// If we have a first type parameter...
|
|
67
|
-
if (node.typeParameters.params[0]) {
|
|
68
|
-
const firstTypeParam = node.typeParameters.params[0];
|
|
69
|
-
// ...and that type parameter is not `any`, `mixed`, or `*`...
|
|
70
|
-
if (firstTypeParam && firstTypeParam.type !== 'AnyTypeAnnotation' && firstTypeParam.type !== 'ExistsTypeAnnotation') {
|
|
71
|
-
// ...then wrap the type parameter with `React.ComponentType<Props>`.
|
|
72
|
-
node.typeParameters.params[0] = j.genericTypeAnnotation(
|
|
73
|
-
// Get the `React.ComponentType` type name, or use the global.
|
|
74
|
-
reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('ComponentType')) : j.identifier('React$ComponentType'),
|
|
75
|
-
// Put the type param we are wrapping as the first and only
|
|
76
|
-
// type argument.
|
|
77
|
-
j.typeParameterInstantiation([firstTypeParam]));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
// If we do not have a first type parameter, or our type parameter is `*`
|
|
81
|
-
// then we want to use `any` instead. This is because using `*` will often
|
|
82
|
-
// cause errors that are unrelated to whether or not the code is correct.
|
|
83
|
-
// Almost all of the time when a user writes `React.Element<*>` they meant
|
|
84
|
-
// `React.Element<any>`. They just felt bad about writing `any`.
|
|
85
|
-
if (node.typeParameters.params.length === 0 || node.typeParameters.params[0].type === 'ExistsTypeAnnotation') {
|
|
86
|
-
node.typeParameters = j.typeParameterInstantiation([j.anyTypeAnnotation()]);
|
|
87
|
-
}
|
|
88
|
-
// Update the type identifier to be `React.Element` or the
|
|
89
|
-
// equivalent global.
|
|
90
|
-
node.id = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Element')) : j.identifier('React$Element');
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// ReactClass<Config> ==> React.ComponentType<Props>
|
|
94
|
-
else if (node.id.type === 'Identifier' && node.id.name === 'ReactClass' && node.typeParameters && node.typeParameters.type === 'TypeParameterInstantiation') {
|
|
95
|
-
// Replace ReactClass with the new type.
|
|
96
|
-
// Get the component type name. Either as a qualified name from our
|
|
97
|
-
// React import or using the global.
|
|
98
|
-
node.id = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('ComponentType')) : j.identifier('React$ComponentType');
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// React$Component<Defaults, Props, State> ==> React.Component<Props, State>
|
|
102
|
-
else if ((node.id.type === 'Identifier' && (node.id.name === 'ReactComponent' || node.id.name === 'React$Component') || componentPattern && componentPattern(node.id)) && node.typeParameters && node.typeParameters.type === 'TypeParameterInstantiation') {
|
|
103
|
-
// Remove the default props type argument.
|
|
104
|
-
if (node.typeParameters.params.length >= 3) {
|
|
105
|
-
node.typeParameters.params.shift();
|
|
106
|
-
}
|
|
107
|
-
// If the user has destructured React and used Component or PureComponent
|
|
108
|
-
// directly then we should not update the identifier of this node.
|
|
109
|
-
if (!(node.id.type === 'Identifier' && (node.id.name === 'Component' || node.id.name === 'PureComponent'))) {
|
|
110
|
-
node.id = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Component')) : j.identifier('React$Component');
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// SyntheticEvent ==> SyntheticEvent<>
|
|
115
|
-
else if (node.id.type === 'Identifier' && SYNTHETIC_EVENT_NAMES.has(node.id.name)) {
|
|
116
|
-
node.typeParameters = j.typeParameterInstantiation([]);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// render(): React.Element<any> ==> render(): React.Node
|
|
121
|
-
if (componentPattern) {
|
|
122
|
-
root.find(j.ClassDeclaration, {
|
|
123
|
-
superClass: componentPattern,
|
|
124
|
-
body: { type: 'ClassBody' }
|
|
125
|
-
}).forEach(handleReactClassPath);
|
|
126
|
-
|
|
127
|
-
root.find(j.ClassExpression, {
|
|
128
|
-
superClass: componentPattern,
|
|
129
|
-
body: { type: 'ClassBody' }
|
|
130
|
-
}).forEach(handleReactClassPath);
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function handleReactClassPath(path) {
|
|
134
|
-
// For every member in the class's body...
|
|
135
|
-
path.node.body.body.forEach(method => {
|
|
136
|
-
// If this member is the component's render method and it has a
|
|
137
|
-
// return type...
|
|
138
|
-
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') {
|
|
139
|
-
const returnType = method.value.returnType;
|
|
140
|
-
// If this is a return type from render that people commonly use then
|
|
141
|
-
// replace it with the new recommendation. React.Node
|
|
142
|
-
if (isRenderReturnReactElement(returnType.typeAnnotation) || returnType.typeAnnotation.type === 'NullableTypeAnnotation' && isRenderReturnReactElement(returnType.typeAnnotation.typeAnnotation)) {
|
|
143
|
-
returnType.typeAnnotation = reactName ? j.qualifiedTypeIdentifier(j.identifier(reactName), j.identifier('Node')) : j.identifier('React$Node');
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
function isRenderReturnReactElement(node) {
|
|
150
|
-
// Is the node React.Element<any>, React.Element<mixed>,
|
|
151
|
-
// or React.Element<*>?
|
|
152
|
-
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'));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return true;
|
|
156
|
-
};
|
|
@@ -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');
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Copyright (c) 2013-present, Facebook, Inc.
|
|
3
|
-
*
|
|
4
|
-
* This source code is licensed under the MIT license found in the
|
|
5
|
-
* LICENSE file in the root directory of this source tree.
|
|
6
|
-
*
|
|
7
|
-
* @format
|
|
8
|
-
*
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
'use strict';
|
|
12
|
-
|
|
13
|
-
module.exports = (j, root) => {
|
|
14
|
-
root.find(j.ObjectTypeAnnotation, { inexact: false, exact: false }).forEach(path => {
|
|
15
|
-
path.node.inexact = true;
|
|
16
|
-
});
|
|
17
|
-
return root.toSource({ tabWidth: 2 });
|
|
18
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Copyright (c) 2013-present, Facebook, Inc.
|
|
5
|
-
*
|
|
6
|
-
* This source code is licensed under the MIT license found in the
|
|
7
|
-
* LICENSE file in the root directory of this source tree.
|
|
8
|
-
*
|
|
9
|
-
* @format
|
|
10
|
-
*
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
const path = require('path');
|
|
14
|
-
const Styled = require('../../../Styled');
|
|
15
|
-
|
|
16
|
-
exports.kind = 'codemod';
|
|
17
|
-
|
|
18
|
-
exports.title = 'Adds `...` to the end of all inexact object types.';
|
|
19
|
-
|
|
20
|
-
exports.description = `
|
|
21
|
-
Flow is changing its object type syntax to be exact by default. See the blog
|
|
22
|
-
post at https://medium.com/flow-type/on-the-roadmap-exact-objects-by-default-16b72933c5cf
|
|
23
|
-
for details. This codemod will add '...' to the end of all inexact object types.
|
|
24
|
-
`;
|
|
25
|
-
exports.transformPath = path.join(__dirname, './codemod.js');
|