tools/vscode_sql_extraction/src/sql_extraction_runner.ts (73 lines of code) (raw):

import {Progress, CancellationToken} from 'vscode'; import {execFile} from 'child_process'; import {Query} from './query'; /** * Runs an executable file provided by the SQL Extraction distribution. */ export class SqlExtractionRunner { constructor(private execPath: string) {} /** * Runs the executable and returns the results. * * @param dir Directory (recursive) to run SQL extraction at. * @param progress Progress bar. * @param token CancellationToken. * @returns List of Json objects (each representing a complete query). */ extractFromDirectory( dir: string, progress: Progress<{ message?: string | undefined; increment?: number | undefined; }>, token: CancellationToken ): Promise<Query[]> { return this.execute( ['-r', '--progress', '--parallel', dir], progress, token ); } private execute( args: string[], progress: Progress<{ message?: string | undefined; increment?: number | undefined; }>, token: CancellationToken ): Promise<Query[]> { if (token.isCancellationRequested) { return Promise.reject(); } return new Promise<Query[]>((resolve, reject) => { progress.report({message: 'Launching SQL Extraction...'}); let json = ''; let errMsg = ''; let totalProgress = 0; const process = execFile(this.execPath, args) .on('close', code => { if (!process.killed && code === 0) { resolve(JSON.parse(json).queries); } else { reject(); } }) .on('error', err => reject(err)); process.stdout!.on('data', data => { json += data; }); process.stderr!.on('data', data => { errMsg += data; const lines = errMsg.split('\n'); // if at least one entire message was received completely up to newline if (lines.length > 1) { for (let i = 0; i < lines.length - 2; i++) { const statement = lines[i]; // if the error message starts with a percentage if (statement.match(/^\d+(\.\d*)?% .*$/)) { const percent = parseFloat(statement); const nextTotalProgress = isNaN(percent) ? totalProgress : percent; const message = statement.substring(statement.indexOf('%' + 2)); progress.report({ message: message, increment: nextTotalProgress - totalProgress, }); totalProgress = nextTotalProgress; } } // save the remainder for later // this works even if '\n' appears at the very end errMsg = lines[lines.length - 1]; } }); token.onCancellationRequested(() => process.kill()); }); } }