74 строки
2.0 KiB
JavaScript
74 строки
2.0 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
module.exports = {
|
|
meta: {
|
|
type: 'problem',
|
|
docs: {
|
|
description:
|
|
'disallow Haste module names in import statements and require calls',
|
|
},
|
|
schema: [],
|
|
},
|
|
|
|
create(context) {
|
|
return {
|
|
ImportDeclaration(node) {
|
|
checkImportForHaste(context, node.source.value, node.source);
|
|
},
|
|
CallExpression(node) {
|
|
if (isStaticRequireCall(node)) {
|
|
const [firstArgument] = node.arguments;
|
|
checkImportForHaste(context, firstArgument.value, firstArgument);
|
|
}
|
|
},
|
|
};
|
|
},
|
|
};
|
|
|
|
function checkImportForHaste(context, importPath, node) {
|
|
if (isLikelyHasteModuleName(importPath)) {
|
|
context.report({
|
|
node,
|
|
message: `"${importPath}" appears to be a Haste module name. Use path-based imports instead.`,
|
|
});
|
|
}
|
|
}
|
|
|
|
function isLikelyHasteModuleName(importPath) {
|
|
// Our heuristic assumes an import path is a Haste module name if it is not a
|
|
// path and doesn't appear to be an npm package. For several years, npm has
|
|
// disallowed uppercase characters in package names.
|
|
//
|
|
// This heuristic has a ~1% false negative rate for the filenames in React
|
|
// Native, which is acceptable since the linter will not complain wrongly and
|
|
// the rate is so low. False negatives that slip through will be caught by
|
|
// tests with Haste disabled.
|
|
return (
|
|
// Exclude relative paths
|
|
!importPath.startsWith('.') &&
|
|
// Exclude package-internal paths and scoped packages
|
|
!importPath.includes('/') &&
|
|
// Include camelCase and UpperCamelCase
|
|
/[A-Z]/.test(importPath)
|
|
);
|
|
}
|
|
|
|
function isStaticRequireCall(node) {
|
|
return (
|
|
node &&
|
|
node.callee &&
|
|
node.callee.type === 'Identifier' &&
|
|
node.callee.name === 'require' &&
|
|
node.arguments.length === 1 &&
|
|
node.arguments[0].type === 'Literal' &&
|
|
typeof node.arguments[0].value === 'string'
|
|
);
|
|
}
|