noMutableArray.js.flow 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. import _ from 'lodash';
  2. const schema = [];
  3. // const x = [];
  4. const isEmptyArrayLiteral = (node) => _.get(node, 'init.type') === 'ArrayExpression' && _.get(node, 'init.elements.length') === 0;
  5. // const x = new Array(); const y = Array();
  6. const isEmptyArrayInstance = (node) => {
  7. if (_.get(node, 'init.type') === 'NewExpression' || _.get(node, 'init.type') === 'CallExpression') {
  8. return _.get(node, 'init.callee.name') === 'Array' && _.get(node, 'init.arguments.length') === 0;
  9. }
  10. return false;
  11. };
  12. const isAnnotationOfEmptyArrayInit = (node) => {
  13. if (_.has(node, 'parent.parent.parent')) {
  14. const parent = _.get(node, 'parent.parent.parent');
  15. const isVariableDeclaration = _.get(parent, 'type') === 'VariableDeclarator';
  16. return isVariableDeclaration && (isEmptyArrayLiteral(parent) || isEmptyArrayInstance(parent));
  17. }
  18. return false;
  19. };
  20. const create = (context) => ({
  21. ArrayTypeAnnotation(node) {
  22. if (!isAnnotationOfEmptyArrayInit(node)) {
  23. context.report({
  24. fix(fixer) {
  25. const rawElementType = context.getSourceCode().getText(node.elementType);
  26. return fixer.replaceText(node, `$ReadOnlyArray<${rawElementType}>`);
  27. },
  28. message: 'Use "$ReadOnlyArray" instead of array shorthand notation',
  29. node,
  30. });
  31. }
  32. },
  33. GenericTypeAnnotation(node) {
  34. if (node.id.name === 'Array' && !isAnnotationOfEmptyArrayInit(node)) {
  35. context.report({
  36. fix(fixer) {
  37. return fixer.replaceText(node.id, '$ReadOnlyArray');
  38. },
  39. message: 'Use "$ReadOnlyArray" instead of "Array"',
  40. node,
  41. });
  42. }
  43. },
  44. });
  45. export default {
  46. create,
  47. meta: {
  48. fixable: 'code',
  49. },
  50. schema,
  51. };