newlineAfterFlowAnnotation.js.flow 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import _ from 'lodash';
  2. const looksLikeFlowFileAnnotation = (comment) => /@(?:no)?flo/ui.test(comment);
  3. const schema = [
  4. {
  5. enum: ['always', 'always-windows', 'never'],
  6. type: 'string',
  7. },
  8. ];
  9. const create = (context) => {
  10. const mode = context.options[0];
  11. const never = mode === 'never';
  12. const newline = mode === 'always-windows' ? '\r\n' : '\n';
  13. return {
  14. Program(node) {
  15. const sourceCode = context.getSourceCode();
  16. const potentialFlowFileAnnotation = _.find(
  17. context.getSourceCode().getAllComments(),
  18. (comment) => looksLikeFlowFileAnnotation(comment.value),
  19. );
  20. if (potentialFlowFileAnnotation) {
  21. const { line } = potentialFlowFileAnnotation.loc.end;
  22. const nextLineIsEmpty = sourceCode.lines[line] === '';
  23. if (!never && !nextLineIsEmpty) {
  24. context.report({
  25. fix: (fixer) => fixer.insertTextAfter(
  26. potentialFlowFileAnnotation,
  27. newline,
  28. ),
  29. message: 'Expected newline after flow annotation',
  30. node,
  31. });
  32. }
  33. if (never && nextLineIsEmpty) {
  34. context.report({
  35. fix: (fixer) => {
  36. const lineBreak = sourceCode.text[potentialFlowFileAnnotation.range[1]];
  37. return fixer.replaceTextRange(
  38. [
  39. potentialFlowFileAnnotation.range[1],
  40. potentialFlowFileAnnotation.range[1] + (
  41. lineBreak === '\r' ? 2 : 1
  42. ),
  43. ],
  44. '',
  45. );
  46. },
  47. message: 'Expected no newline after flow annotation',
  48. node,
  49. });
  50. }
  51. }
  52. },
  53. };
  54. };
  55. export default {
  56. create,
  57. meta: {
  58. fixable: 'code',
  59. },
  60. schema,
  61. };