import * as cp from 'child_process' ; import * as vscode from 'vscode' ; import * as util from 'util' ; import { ProtoError , parseProtoError } from './protoError' ; export interface LinterError { proto : ProtoError ; range : vscode . Range ; } export default class Linter { private codeDocument : vscode . TextDocument ; constructor ( document ) { this . codeDocument = document ; } public async lint ( ) { const result = await this . runProtoLint ( ) ; if ( ! result ) { return [ ] ; } const lintingErrors = this . parseErrors ( result ) ; if ( lintingErrors . length === 0 ) { vscode . window . showErrorMessage ( "protolint: " + result ) ; return [ ] ; } return lintingErrors ; } private async runProtoLint ( ) { if ( ! vscode . workspace . workspaceFolders ) { return "" ; } let workspaceFolder = vscode . workspace . getWorkspaceFolder ( this . codeDocument . uri ) || vscode . workspace . workspaceFolders [ 0 ] ; const cmd = `protolint lint -config_dir_path="${ workspaceFolder . uri . fsPath }" "${ this . codeDocument . uri . fsPath }"` ; let lintResults = "" ; const exec = util . promisify ( cp . exec ) ; await exec ( cmd ) . catch ( ( error ) => lintResults = error . stderr ) ; return lintResults ; } private parseErrors ( errorStr ) { let errors = errorStr . split ( '\n' ) || [ ] ; var result = errors . reduce ( ( errors , currentError ) => { const parsedError = parseProtoError ( currentError ) ; if ( ! parsedError . reason ) { return errors ; } const linterError = { proto : parsedError , range : this . codeDocument . lineAt ( parsedError . line - 1 ) . range } ; return errors . concat ( linterError ) ; } , [ ] ) ; return result ; } }