SHARE
TWEET

Untitled

a guest Apr 18th, 2019 72 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // @flow
  2.  
  3. let { uniq, flatten } = require('lodash');
  4. let chalk = require('chalk');
  5. let dedent = require('dedent');
  6. let { isEqual, padStart, padEnd, trimEnd } = require('lodash');
  7. let fs = require('fs');
  8.  
  9. // NOTE CLASSIC
  10. const indent = indentLevel => (...args) => {
  11.   const spaces = ``.repeat(indentLevel);
  12.   const result = dedent(...args);
  13.   return result.split('\n').map(x => `${spaces}${x}`).join('\n');
  14. };
  15.  
  16. /* ::
  17. type TFlowPoint = {
  18.   line: number,
  19.   column: number,
  20.   offset: number,
  21. }
  22. type TFlowLocation = {
  23.   source: string,
  24.   type: 'JsonFile' | 'SourceFile' | 'LibFile',
  25.   start: TFlowPoint,
  26.   end: TFlowPoint,
  27. }
  28. type TFlowMessage = {
  29.   context: string,
  30.   descr: string,
  31.   type: 'Blame' | 'Comment',
  32.   loc: TFlowLocation,
  33.   path: string,
  34.   line: number,
  35.   endline: number,
  36.   start: number,
  37.   end: number,
  38. }
  39.  
  40. type TFlowError = {
  41.   kind: string,
  42.   level: string,
  43.   message: Array<TFlowMessage>,
  44. }
  45.  
  46. type TFlowReport = {
  47.   flowVersion: number,
  48.   errors: Array<TFlowError>,
  49.   passed: boolean,
  50. }
  51. */
  52.  
  53. // NOTE CLASSIC
  54. const suck = stream => {
  55.   return new Promise(function(yell, cry) {
  56.     const content = [];
  57.     process.stdin.on('readable', () => {
  58.       const data: ?Buffer = (process.stdin.read(): any);
  59.       if (data) content.push(data);
  60.       else yell(Buffer.concat(content).toString());
  61.     });
  62.   });
  63. };
  64.  
  65. const suckText = async (...args) => (await suck(...args)).toString();
  66.  
  67. const does_not_contain_dot_directory = message =>
  68.   message.path.split('/').every(name => !name.startsWith('.'));
  69. const does_not_contain_node_modules = message =>
  70.   message.path.split('/').every(name => name !== 'node_modules');
  71.  
  72. // NOTE CLASSIC
  73. const not = fn => (...args) => !fn(...args);
  74. // NOTE CLASSIC
  75. const divide = (xs, pred) => [xs.filter(pred), xs.filter(not(pred))];
  76.  
  77. const workdir = '/Users/michieldral/Projects/uButler Portal/';
  78. // NOTE CLASSIC
  79. const without_prefix = (string: string, prefix: string) => {
  80.   if (!string.startsWith(prefix)) return string;
  81.   else return string.slice(prefix.length);
  82. };
  83. // const pretty_print = (obj) => JSON.stringify(obj, null, 2)
  84.  
  85. // const FLOW_START = { line: 0, column: 0, offset: 0 };
  86. // const FLOW_END = { line: Infinity, column: Infinity, offset: Infinity };
  87. // const string_range = (string, start: TFlowPoint, end: TFlowPoint) => {
  88. //   return string.slice(start.column, end.column);
  89. // }
  90. const decorate_string_range = (range: TFlowLocation, string, mapFn) => {
  91.   return [
  92.     string.slice(0, range.start.column - 1),
  93.     mapFn(string.slice(range.start.column - 1, range.end.column)),
  94.     string.slice(range.end.column, Infinity),
  95.   ].join('');
  96. };
  97.  
  98. const count_regex = (str, regex) => {
  99.   let m = str.match(regex);
  100.   return m ? m.length : 0;
  101. };
  102.  
  103. const count_control_char = str => {
  104.   return count_regex(str, /[\x00-\x1F\x7F-\x9F]/g) * 5;
  105. };
  106.  
  107. const mark_characters = str => {
  108.   return str.replace(
  109.     /([ ]*)(.*[^ ])([ ]*)/,
  110.     '$1' + chalk.bgRed.black('$2') + '$3',
  111.   );
  112. };
  113.  
  114. const prefix_lines = (str, prefix) => {
  115.   return str.split('\n').map(line => `${prefix}${line}`).join('\n');
  116. };
  117.  
  118. const print_code = async message => {
  119.   if (!message.loc) throw new Error();
  120.   const loc = message.loc;
  121.  
  122.   const all_lines = fs.readFileSync(loc.source).toString().split('\n');
  123.  
  124.   let indented;
  125.   if (loc.start.line === loc.end.line) {
  126.     const before = all_lines.slice(loc.start.line - 3, loc.start.line - 1);
  127.     const the_line = all_lines[loc.start.line - 1];
  128.     const after = all_lines.slice(loc.end.line, loc.end.line + 2);
  129.  
  130.     const the_line_before = the_line.slice(0, loc.start.column - 1);
  131.     const the_line_marked = the_line.slice(
  132.       loc.start.column - 1,
  133.       loc.end.column,
  134.     );
  135.     const the_line_after = the_line.slice(loc.end.column);
  136.  
  137.     indented =
  138.       before.join('\n') +
  139.       '\n' +
  140.       the_line_before +
  141.       mark_characters(the_line_marked) +
  142.       the_line_after +
  143.       '\n' +
  144.       after.join('\n');
  145.   } else {
  146.     const before = all_lines.slice(loc.start.line - 3, loc.start.line - 1);
  147.     const partial_first = all_lines[loc.start.line - 1];
  148.     const middle = all_lines.slice(loc.start.line, loc.end.line - 1);
  149.     const partial_last = all_lines[loc.end.line - 1];
  150.     const after = all_lines.slice(loc.end.line, loc.end.line + 2);
  151.  
  152.     const middle_with_marks = middle.map(line => mark_characters(line));
  153.  
  154.     const partial_first_unmarked = partial_first.slice(0, loc.start.column - 1);
  155.     const partial_first_marked = partial_first.slice(loc.start.column - 1);
  156.  
  157.     const partial_last_marked = partial_last.slice(0, loc.end.column);
  158.     const partial_last_unmarked = partial_last.slice(loc.end.column);
  159.  
  160.     indented =
  161.       before.join('\n') +
  162.       '\n' +
  163.       partial_first_unmarked +
  164.       mark_characters(partial_first_marked) +
  165.       '\n' +
  166.       middle_with_marks.join('\n') +
  167.       '\n' +
  168.       mark_characters(partial_last_marked) +
  169.       partial_last_unmarked +
  170.       '\n' +
  171.       after.join('\n');
  172.   }
  173.  
  174.   let dedented = dedent(
  175.     indented.split('\n').map(x => `  ${x}`).join('\n'),
  176.   ).split('\n');
  177.  
  178.   let box_width = Math.max(
  179.     dedented
  180.       .slice()
  181.       // Remove control characters (colors)
  182.       .map(x => x.replace(/[\x00-\x1F\x7F-\x9F]/g, ''))
  183.       .sort((a, b) => b.length - a.length)[0].length,
  184.     50,
  185.   );
  186.  
  187.   return dedented
  188.     .map((line, i) => ` ${padEnd(loc.start.line - 2 + i + ':', 6)}${line}`)
  189.     .map(line => padEnd(line, box_width + count_control_char(line) + 8))
  190.     .map(line => chalk.bgWhite.black(line))
  191.     .join('\n');
  192. };
  193.  
  194. const main = async ({ show_missing_annotations = false }) => {
  195.   const json = await suckText(process.stdin);
  196.   const result = JSON.parse(json.toString());
  197.  
  198.   const allKinds = uniq(result.errors.map(x => x.kind));
  199.   const allLevels = uniq(result.errors.map(x => x.level));
  200.  
  201.   const allMessages = flatten(result.errors.map(x => x.message));
  202.   const allTypes = uniq(allMessages.map(x => x.type));
  203.   const allLocTypes = uniq(allMessages.map(x => x.loc && x.loc.type));
  204.  
  205.   console.log('Object.keys(result):', Object.keys(result));
  206.   console.log('allKinds:', allKinds);
  207.   console.log('allLevels:', allLevels);
  208.   console.log('allLocTypes:', allLocTypes);
  209.   console.log('allTypes:', allTypes);
  210.  
  211.   const errors = result.errors
  212.     .filter(err => err.message.every(does_not_contain_dot_directory))
  213.     .filter(err => err.message.every(does_not_contain_node_modules));
  214.  
  215.   const [parse_errors, infer_errors] = divide(
  216.     errors,
  217.     err => err.kind === 'parse',
  218.   );
  219.  
  220.   const parse_messages = parse_errors.map(
  221.     error => dedent`
  222.     ${chalk.red(`===`)} Parse error in file
  223.     ${without_prefix(error.message[0].path, workdir)}
  224.   `,
  225.   );
  226.   console.log('\n\n', parse_messages.join('\n'));
  227.  
  228.   const infer_messages = await Promise.all(
  229.     infer_errors.map(async (error: TFlowError) => {
  230.       const structure = error.message.map(m => m.type);
  231.  
  232.       if (isEqual(structure, ['Blame', 'Comment'])) {
  233.         const [blame, comment] = error.message;
  234.  
  235.         if (!blame.loc) throw new Error();
  236.         if (!show_missing_annotations && comment.descr === 'Missing annotation')
  237.           return '';
  238.  
  239.         const loc = blame.loc;
  240.  
  241.         let code = await print_code(blame);
  242.  
  243.         return indent(0)`
  244.         ${chalk.blue(`[File]`)} In ${chalk.blue(
  245.           without_prefix(blame.path, workdir),
  246.         )}
  247.         ${prefix_lines(code, chalk.blue(`[Code] `))}
  248.         ${chalk.blue(`[Line]`)}
  249.         ${chalk.blue(`[Line]`)} > ${chalk.yellow(blame.descr)}
  250.         ${chalk.blue(`[Line]`)} ${comment.descr}
  251.       `;
  252.       } else if (isEqual(structure, ['Blame', 'Comment', 'Blame'])) {
  253.         const [blame1, comment, blame2] = error.message;
  254.  
  255.         if (!blame1.loc || !blame2.loc) throw new Error();
  256.         if (!show_missing_annotations && comment.descr === 'Missing annotation')
  257.           return '';
  258.  
  259.         let code1 = await print_code(blame1);
  260.         let code2 = await print_code(blame2);
  261.  
  262.         return indent(0)`
  263.         ${chalk.blue(`[File]`)} In ${chalk.blue(
  264.           without_prefix(blame1.path, workdir),
  265.         )}
  266.         ${prefix_lines(code1, chalk.blue(`[Code] `))}
  267.         ${chalk.blue(`[Line]`)}
  268.         ${chalk.blue(`[Line]`)} > ${chalk.yellow(blame1.descr)}
  269.         ${chalk.blue(`[Line]`)} ${comment.descr}
  270.         ${chalk.blue(`[Line]`)} > ${chalk.yellow(blame2.descr)}
  271.         ${chalk.blue(`[Line]`)}
  272.         ${chalk.blue(`[File]`)} In ${chalk.blue(
  273.           without_prefix(blame2.path, workdir),
  274.         )}
  275.         ${prefix_lines(code2, chalk.blue(`[Code] `))}
  276.       `;
  277.       } else {
  278.         return chalk.green(structure.join(', '));
  279.       }
  280.     }),
  281.   );
  282.  
  283.   console.log('\n');
  284.   console.log(infer_messages.filter(Boolean).join('\n\n\n'));
  285. };
  286.  
  287. main({}).catch(err => {
  288.   console.log('err:', err);
  289. });
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top