Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // @flow
- let { uniq, flatten } = require('lodash');
- let chalk = require('chalk');
- let dedent = require('dedent');
- let { isEqual, padStart, padEnd, trimEnd } = require('lodash');
- let fs = require('fs');
- // NOTE CLASSIC
- const indent = indentLevel => (...args) => {
- const spaces = ``.repeat(indentLevel);
- const result = dedent(...args);
- return result.split('\n').map(x => `${spaces}${x}`).join('\n');
- };
- /* ::
- type TFlowPoint = {
- line: number,
- column: number,
- offset: number,
- }
- type TFlowLocation = {
- source: string,
- type: 'JsonFile' | 'SourceFile' | 'LibFile',
- start: TFlowPoint,
- end: TFlowPoint,
- }
- type TFlowMessage = {
- context: string,
- descr: string,
- type: 'Blame' | 'Comment',
- loc: TFlowLocation,
- path: string,
- line: number,
- endline: number,
- start: number,
- end: number,
- }
- type TFlowError = {
- kind: string,
- level: string,
- message: Array<TFlowMessage>,
- }
- type TFlowReport = {
- flowVersion: number,
- errors: Array<TFlowError>,
- passed: boolean,
- }
- */
- // NOTE CLASSIC
- const suck = stream => {
- return new Promise(function(yell, cry) {
- const content = [];
- process.stdin.on('readable', () => {
- const data: ?Buffer = (process.stdin.read(): any);
- if (data) content.push(data);
- else yell(Buffer.concat(content).toString());
- });
- });
- };
- const suckText = async (...args) => (await suck(...args)).toString();
- const does_not_contain_dot_directory = message =>
- message.path.split('/').every(name => !name.startsWith('.'));
- const does_not_contain_node_modules = message =>
- message.path.split('/').every(name => name !== 'node_modules');
- // NOTE CLASSIC
- const not = fn => (...args) => !fn(...args);
- // NOTE CLASSIC
- const divide = (xs, pred) => [xs.filter(pred), xs.filter(not(pred))];
- const workdir = '/Users/michieldral/Projects/uButler Portal/';
- // NOTE CLASSIC
- const without_prefix = (string: string, prefix: string) => {
- if (!string.startsWith(prefix)) return string;
- else return string.slice(prefix.length);
- };
- // const pretty_print = (obj) => JSON.stringify(obj, null, 2)
- // const FLOW_START = { line: 0, column: 0, offset: 0 };
- // const FLOW_END = { line: Infinity, column: Infinity, offset: Infinity };
- // const string_range = (string, start: TFlowPoint, end: TFlowPoint) => {
- // return string.slice(start.column, end.column);
- // }
- const decorate_string_range = (range: TFlowLocation, string, mapFn) => {
- return [
- string.slice(0, range.start.column - 1),
- mapFn(string.slice(range.start.column - 1, range.end.column)),
- string.slice(range.end.column, Infinity),
- ].join('');
- };
- const count_regex = (str, regex) => {
- let m = str.match(regex);
- return m ? m.length : 0;
- };
- const count_control_char = str => {
- return count_regex(str, /[\x00-\x1F\x7F-\x9F]/g) * 5;
- };
- const mark_characters = str => {
- return str.replace(
- /([ ]*)(.*[^ ])([ ]*)/,
- '$1' + chalk.bgRed.black('$2') + '$3',
- );
- };
- const prefix_lines = (str, prefix) => {
- return str.split('\n').map(line => `${prefix}${line}`).join('\n');
- };
- const print_code = async message => {
- if (!message.loc) throw new Error();
- const loc = message.loc;
- const all_lines = fs.readFileSync(loc.source).toString().split('\n');
- let indented;
- if (loc.start.line === loc.end.line) {
- const before = all_lines.slice(loc.start.line - 3, loc.start.line - 1);
- const the_line = all_lines[loc.start.line - 1];
- const after = all_lines.slice(loc.end.line, loc.end.line + 2);
- const the_line_before = the_line.slice(0, loc.start.column - 1);
- const the_line_marked = the_line.slice(
- loc.start.column - 1,
- loc.end.column,
- );
- const the_line_after = the_line.slice(loc.end.column);
- indented =
- before.join('\n') +
- '\n' +
- the_line_before +
- mark_characters(the_line_marked) +
- the_line_after +
- '\n' +
- after.join('\n');
- } else {
- const before = all_lines.slice(loc.start.line - 3, loc.start.line - 1);
- const partial_first = all_lines[loc.start.line - 1];
- const middle = all_lines.slice(loc.start.line, loc.end.line - 1);
- const partial_last = all_lines[loc.end.line - 1];
- const after = all_lines.slice(loc.end.line, loc.end.line + 2);
- const middle_with_marks = middle.map(line => mark_characters(line));
- const partial_first_unmarked = partial_first.slice(0, loc.start.column - 1);
- const partial_first_marked = partial_first.slice(loc.start.column - 1);
- const partial_last_marked = partial_last.slice(0, loc.end.column);
- const partial_last_unmarked = partial_last.slice(loc.end.column);
- indented =
- before.join('\n') +
- '\n' +
- partial_first_unmarked +
- mark_characters(partial_first_marked) +
- '\n' +
- middle_with_marks.join('\n') +
- '\n' +
- mark_characters(partial_last_marked) +
- partial_last_unmarked +
- '\n' +
- after.join('\n');
- }
- let dedented = dedent(
- indented.split('\n').map(x => ` ${x}`).join('\n'),
- ).split('\n');
- let box_width = Math.max(
- dedented
- .slice()
- // Remove control characters (colors)
- .map(x => x.replace(/[\x00-\x1F\x7F-\x9F]/g, ''))
- .sort((a, b) => b.length - a.length)[0].length,
- 50,
- );
- return dedented
- .map((line, i) => ` ${padEnd(loc.start.line - 2 + i + ':', 6)}${line}`)
- .map(line => padEnd(line, box_width + count_control_char(line) + 8))
- .map(line => chalk.bgWhite.black(line))
- .join('\n');
- };
- const main = async ({ show_missing_annotations = false }) => {
- const json = await suckText(process.stdin);
- const result = JSON.parse(json.toString());
- const allKinds = uniq(result.errors.map(x => x.kind));
- const allLevels = uniq(result.errors.map(x => x.level));
- const allMessages = flatten(result.errors.map(x => x.message));
- const allTypes = uniq(allMessages.map(x => x.type));
- const allLocTypes = uniq(allMessages.map(x => x.loc && x.loc.type));
- console.log('Object.keys(result):', Object.keys(result));
- console.log('allKinds:', allKinds);
- console.log('allLevels:', allLevels);
- console.log('allLocTypes:', allLocTypes);
- console.log('allTypes:', allTypes);
- const errors = result.errors
- .filter(err => err.message.every(does_not_contain_dot_directory))
- .filter(err => err.message.every(does_not_contain_node_modules));
- const [parse_errors, infer_errors] = divide(
- errors,
- err => err.kind === 'parse',
- );
- const parse_messages = parse_errors.map(
- error => dedent`
- ${chalk.red(`===`)} Parse error in file
- ${without_prefix(error.message[0].path, workdir)}
- `,
- );
- console.log('\n\n', parse_messages.join('\n'));
- const infer_messages = await Promise.all(
- infer_errors.map(async (error: TFlowError) => {
- const structure = error.message.map(m => m.type);
- if (isEqual(structure, ['Blame', 'Comment'])) {
- const [blame, comment] = error.message;
- if (!blame.loc) throw new Error();
- if (!show_missing_annotations && comment.descr === 'Missing annotation')
- return '';
- const loc = blame.loc;
- let code = await print_code(blame);
- return indent(0)`
- ${chalk.blue(`[File]`)} In ${chalk.blue(
- without_prefix(blame.path, workdir),
- )}
- ${prefix_lines(code, chalk.blue(`[Code] `))}
- ${chalk.blue(`[Line]`)}
- ${chalk.blue(`[Line]`)} > ${chalk.yellow(blame.descr)}
- ${chalk.blue(`[Line]`)} ${comment.descr}
- `;
- } else if (isEqual(structure, ['Blame', 'Comment', 'Blame'])) {
- const [blame1, comment, blame2] = error.message;
- if (!blame1.loc || !blame2.loc) throw new Error();
- if (!show_missing_annotations && comment.descr === 'Missing annotation')
- return '';
- let code1 = await print_code(blame1);
- let code2 = await print_code(blame2);
- return indent(0)`
- ${chalk.blue(`[File]`)} In ${chalk.blue(
- without_prefix(blame1.path, workdir),
- )}
- ${prefix_lines(code1, chalk.blue(`[Code] `))}
- ${chalk.blue(`[Line]`)}
- ${chalk.blue(`[Line]`)} > ${chalk.yellow(blame1.descr)}
- ${chalk.blue(`[Line]`)} ${comment.descr}
- ${chalk.blue(`[Line]`)} > ${chalk.yellow(blame2.descr)}
- ${chalk.blue(`[Line]`)}
- ${chalk.blue(`[File]`)} In ${chalk.blue(
- without_prefix(blame2.path, workdir),
- )}
- ${prefix_lines(code2, chalk.blue(`[Code] `))}
- `;
- } else {
- return chalk.green(structure.join(', '));
- }
- }),
- );
- console.log('\n');
- console.log(infer_messages.filter(Boolean).join('\n\n\n'));
- };
- main({}).catch(err => {
- console.log('err:', err);
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement