|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +import * as path from 'path'; |
| 4 | +import * as baseLinter from './baseLinter'; |
| 5 | +import {ILintMessage} from './baseLinter'; |
| 6 | +import * as settings from './../common/configSettings'; |
| 7 | +import {OutputChannel, window} from 'vscode'; |
| 8 | +import { exec } from 'child_process'; |
| 9 | +import {sendCommand} from './../common/childProc'; |
| 10 | + |
| 11 | +export class Linter extends baseLinter.BaseLinter { |
| 12 | + constructor(rootDir: string, pythonSettings: settings.IPythonSettings, outputChannel: OutputChannel) { |
| 13 | + super("pydocstyle", pythonSettings, outputChannel); |
| 14 | + } |
| 15 | + |
| 16 | + public runLinter(filePath: string, txtDocumentLines: string[]): Promise<baseLinter.ILintMessage[]> { |
| 17 | + if (!this.pythonSettings.linting.pydocstyleEnabled) { |
| 18 | + return Promise.resolve([]); |
| 19 | + } |
| 20 | + |
| 21 | + var pydocStylePath = this.pythonSettings.linting.pydocStylePath; |
| 22 | + var cmdLine = `${pydocStylePath} "${filePath}"`; |
| 23 | + return new Promise<baseLinter.ILintMessage[]>(resolve => { |
| 24 | + this.run(cmdLine, filePath, txtDocumentLines).then(messages => { |
| 25 | + //All messages in pep8 are treated as warnings for now |
| 26 | + messages.forEach(msg => { |
| 27 | + msg.severity = baseLinter.LintMessageSeverity.Information; |
| 28 | + }); |
| 29 | + |
| 30 | + resolve(messages); |
| 31 | + }); |
| 32 | + }); |
| 33 | + } |
| 34 | + |
| 35 | + protected run(commandLine: string, filePath: string, txtDocumentLines: string[]): Promise<ILintMessage[]> { |
| 36 | + var outputChannel = this.outputChannel; |
| 37 | + var linterId = this.Id; |
| 38 | + |
| 39 | + return new Promise<ILintMessage[]>((resolve, reject) => { |
| 40 | + var fileDir = path.dirname(filePath); |
| 41 | + sendCommand(commandLine, fileDir, true).then(data => { |
| 42 | + outputChannel.clear(); |
| 43 | + outputChannel.append(data); |
| 44 | + var outputLines = data.split(/\r?\n/g); |
| 45 | + var diagnostics: ILintMessage[] = []; |
| 46 | + var baseFileName = path.basename(filePath); |
| 47 | + |
| 48 | + //Remember, the first line of the response contains the file name and line number, the next line contains the error message |
| 49 | + //So we have two lines per message, hence we need to take lines in pairs |
| 50 | + var maxLines = this.pythonSettings.linting.maxNumberOfProblems * 2; |
| 51 | + //First line is almost always empty |
| 52 | + while (outputLines.length > 0 && outputLines[0].trim().length === 0) { |
| 53 | + outputLines.splice(0, 1); |
| 54 | + } |
| 55 | + outputLines = outputLines.filter((value, index) => index < maxLines); |
| 56 | + |
| 57 | + //Iterate through the lines (skipping the messages) |
| 58 | + //So, just iterate the response in pairs |
| 59 | + for (var counter = 0; counter < outputLines.length; counter = counter + 2) { |
| 60 | + try { |
| 61 | + var line = outputLines[counter]; |
| 62 | + if (line.trim().length === 0) { |
| 63 | + continue; |
| 64 | + } |
| 65 | + var messageLine = outputLines[counter + 1]; |
| 66 | + var lineNumber = parseInt(line.substring(line.indexOf(baseFileName) + baseFileName.length + 1)); |
| 67 | + var code = messageLine.substring(0, messageLine.indexOf(":")).trim(); |
| 68 | + var message = messageLine.substring(messageLine.indexOf(":") + 1).trim(); |
| 69 | + |
| 70 | + var sourceLine = txtDocumentLines[lineNumber - 1]; |
| 71 | + var trmmedSourceLine = sourceLine.trim(); |
| 72 | + var sourceStart = sourceLine.indexOf(trmmedSourceLine); |
| 73 | + var endCol = sourceStart + trmmedSourceLine.length; |
| 74 | + |
| 75 | + diagnostics.push({ |
| 76 | + code: code, |
| 77 | + message: message, |
| 78 | + column: sourceStart, |
| 79 | + line: lineNumber, |
| 80 | + type: "", |
| 81 | + provider: this.Id |
| 82 | + }); |
| 83 | + } |
| 84 | + catch (ex) { |
| 85 | + //Hmm, need to handle this later |
| 86 | + var y = ""; |
| 87 | + } |
| 88 | + } |
| 89 | + |
| 90 | + resolve(diagnostics); |
| 91 | + }, error => { |
| 92 | + outputChannel.appendLine(`Linting with ${linterId} failed. If not installed please turn if off in settings.\n ${error}`); |
| 93 | + window.showInformationMessage(`Linting with ${linterId} failed. If not installed please turn if off in settings. View Python output for details.`); |
| 94 | + }); |
| 95 | + }); |
| 96 | + } |
| 97 | +} |
0 commit comments