forked from react/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplugin-warn-on-deep-imports.js
More file actions
124 lines (106 loc) · 3.08 KB
/
Copy pathplugin-warn-on-deep-imports.js
File metadata and controls
124 lines (106 loc) · 3.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @noflow
*/
'use strict';
function getWarningMessage(importPath, loc, source) {
const message = `Deep imports from the 'react-native' package are deprecated ('${importPath}').`;
if (source !== undefined) {
return `${message} Source: ${source} ${loc ? `${loc.start.line}:${loc.start.column}` : ''}`;
}
return message;
}
function createWarning(t, importPath, loc, source) {
const warningMessage = getWarningMessage(importPath, loc, source);
const warning = t.expressionStatement(
t.callExpression(
t.memberExpression(t.identifier('console'), t.identifier('warn')),
[t.stringLiteral(warningMessage)],
),
);
return warning;
}
function isDeepReactNativeImport(source) {
const parts = source.split('/');
return parts.length > 1 && parts[0] === 'react-native';
}
function withLocation(node, loc) {
if (!node.loc) {
return {...node, loc};
}
return node;
}
module.exports = ({types: t}) => ({
name: 'warn-on-deep-imports',
visitor: {
ImportDeclaration(path, state) {
const source = path.node.source.value;
if (isDeepReactNativeImport(source)) {
const loc = path.node.loc;
state.import.push({source, loc});
}
},
CallExpression(path, state) {
const callee = path.get('callee');
const args = path.get('arguments');
if (
callee.isIdentifier({name: 'require'}) &&
args.length === 1 &&
args[0].isStringLiteral()
) {
const source =
args[0].node.type === 'StringLiteral' ? args[0].node.value : '';
if (isDeepReactNativeImport(source)) {
const loc = path.node.loc;
state.require.push({source, loc});
}
}
},
ExportNamedDeclaration(path, state) {
const source = path.node.source;
if (source && isDeepReactNativeImport(source.value)) {
const loc = path.node.loc;
state.export.push({source: source.value, loc});
}
},
Program: {
enter(path, state) {
state.require = [];
state.import = [];
state.export = [];
},
exit(path, state) {
const {body} = path.node;
const requireWarnings = state.require.map(value =>
withLocation(
createWarning(t, value.source, value.loc, state.filename),
value.loc,
),
);
const importWarnings = state.import.map(value =>
withLocation(
createWarning(t, value.source, value.loc, state.filename),
value.loc,
),
);
const exportWarnings = state.export.map(value =>
withLocation(
createWarning(t, value.source, value.loc, state.filename),
value.loc,
),
);
const warnings = [
...requireWarnings,
...importWarnings,
...exportWarnings,
];
body.push(...warnings);
},
},
},
});