From 87cf2e7aa0e0382af072f60fff29012c62567b3c Mon Sep 17 00:00:00 2001 From: "J. Cliff Dyer" Date: Fri, 29 Dec 2017 14:18:59 -0500 Subject: [PATCH 1/4] Update pylint msg-template to show human-friendly error symbols. Fixes #382 --- package.json | 2 +- src/client/linters/pylint.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a5850541fe92..a834dd3717aa 100644 --- a/package.json +++ b/package.json @@ -1170,7 +1170,7 @@ }, "python.linting.pylintArgs": { "type": "array", - "description": "Arguments passed in. Each argument is a separate item in the array.", + "description": "Arguments passed in. Each argument is a separate item in the array. --msg-template is set by VSCode and cannot be overridden here.", "default": [], "items": { "type": "string" diff --git a/src/client/linters/pylint.ts b/src/client/linters/pylint.ts index 099315a5e460..e0681a6034d3 100644 --- a/src/client/linters/pylint.ts +++ b/src/client/linters/pylint.ts @@ -11,7 +11,7 @@ export class Linter extends baseLinter.BaseLinter { } protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { - const messages = await this.run(['--msg-template=\'{line},{column},{category},{msg_id}:{msg}\'', '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation); + const messages = await this.run(['--msg-template=\'{line},{column},{category},{msg_id}:{msg} ({symbol})\'', '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.pylintCategorySeverity); }); From d35e8dcc803615f78c56d91e1dd1486d5f497fa3 Mon Sep 17 00:00:00 2001 From: "J. Cliff Dyer" Date: Tue, 2 Jan 2018 11:24:24 -0500 Subject: [PATCH 2/4] Add ability to override pylint message template. --- package.json | 8 +++++++- src/client/common/configSettings.ts | 3 ++- src/client/linters/pylint.ts | 3 ++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a834dd3717aa..b13b22eb9450 100644 --- a/package.json +++ b/package.json @@ -1170,7 +1170,7 @@ }, "python.linting.pylintArgs": { "type": "array", - "description": "Arguments passed in. Each argument is a separate item in the array. --msg-template is set by VSCode and cannot be overridden here.", + "description": "Arguments passed in. Each argument is a separate item in the array. --msg-template is set by VSCode and cannot be overridden here. Use python.linting.pylintMsgTemplate instead.", "default": [], "items": { "type": "string" @@ -1216,6 +1216,12 @@ }, "scope": "resource" }, + "python.linting.pylintMsgTemplate": { + "type": "string", + "description": "Controls the message template for linting results, as a new-style python format string. The provided value will be appended to '{line},{column},{category},', which is required by VSCode. The previous message format, using numeric message codes, can be restored by setting this to '{msg_id}:{msg}'. Available fields are described at https://pylint.readthedocs.io/en/latest/user_guide/output.html.", + "default": "{msg} ({symbol})", + "scope": "resource" + }, "python.formatting.provider": { "type": "string", "default": "autopep8", diff --git a/src/client/common/configSettings.ts b/src/client/common/configSettings.ts index 6899e248da85..ed25cece3f92 100644 --- a/src/client/common/configSettings.ts +++ b/src/client/common/configSettings.ts @@ -76,6 +76,7 @@ export interface ILintingSettings { prospectorArgs: string[]; pylintEnabled: boolean; pylintArgs: string[]; + pylintMsgTemplate: string; pep8Enabled: boolean; pep8Args: string[]; pylamaEnabled: boolean; @@ -246,7 +247,7 @@ export class PythonSettings extends EventEmitter implements IPythonSettings { pylamaArgs: [], pylamaEnabled: false, pylamaPath: 'pylama', prospectorArgs: [], prospectorEnabled: false, prospectorPath: 'prospector', pydocstyleArgs: [], pydocstyleEnabled: false, pydocstylePath: 'pydocstyle', - pylintArgs: [], pylintEnabled: false, pylintPath: 'pylint', + pylintArgs: [], pylintEnabled: false, pylintPath: 'pylint', pylintMsgTemplate: '{msg_id}:{msg}', pylintCategorySeverity: { convention: vscode.DiagnosticSeverity.Hint, error: vscode.DiagnosticSeverity.Error, diff --git a/src/client/linters/pylint.ts b/src/client/linters/pylint.ts index e0681a6034d3..ae9a65a8c60a 100644 --- a/src/client/linters/pylint.ts +++ b/src/client/linters/pylint.ts @@ -11,7 +11,8 @@ export class Linter extends baseLinter.BaseLinter { } protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { - const messages = await this.run(['--msg-template=\'{line},{column},{category},{msg_id}:{msg} ({symbol})\'', '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation); + const msgTemplate = `'{line},{column},{category},${this.pythonSettings.linting.pylintMsgTemplate}'`; + const messages = await this.run([`--msg-template=${msgTemplate}`, '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.pylintCategorySeverity); }); From 656c3d80474591cfab21e4b57b8bc1de0ca18d5e Mon Sep 17 00:00:00 2001 From: "J. Cliff Dyer" Date: Tue, 9 Jan 2018 22:32:58 -0500 Subject: [PATCH 3/4] Provide enumerated output options. Allow creating diagnostics with pre-formatted message strings. --- package.json | 8 ++++++-- src/client/common/constants.ts | 1 + src/client/linters/baseLinter.ts | 4 +++- src/client/linters/prospector.ts | 3 ++- src/client/linters/pylint.ts | 17 +++++++++++++++-- src/client/providers/lintProvider.ts | 9 ++++++++- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index b13b22eb9450..43be13460594 100644 --- a/package.json +++ b/package.json @@ -1218,8 +1218,12 @@ }, "python.linting.pylintMsgTemplate": { "type": "string", - "description": "Controls the message template for linting results, as a new-style python format string. The provided value will be appended to '{line},{column},{category},', which is required by VSCode. The previous message format, using numeric message codes, can be restored by setting this to '{msg_id}:{msg}'. Available fields are described at https://pylint.readthedocs.io/en/latest/user_guide/output.html.", - "default": "{msg} ({symbol})", + "description": "Controls the message template for linting results. Options are 'standard' and 'legacy'. 'standard' displays error codes as symbolic names like 'missing-docstring'. 'legacy' displays error codes as alphanumeric codes like 'C0111'.", + "default": "legacy", + "enum": [ + "standard", + "legacy" + ], "scope": "resource" }, "python.formatting.provider": { diff --git a/src/client/common/constants.ts b/src/client/common/constants.ts index cde72d22fd21..c896dff1daf1 100644 --- a/src/client/common/constants.ts +++ b/src/client/common/constants.ts @@ -49,6 +49,7 @@ export namespace Delays { export namespace LinterErrors { export namespace pylint { export const InvalidSyntax = 'E0001'; + export const InvalidSyntaxSymbolic = 'invalid-syntax'; } export namespace prospector { export const InvalidSyntax = 'F999'; diff --git a/src/client/linters/baseLinter.ts b/src/client/linters/baseLinter.ts index eebc825af883..edac4b67a812 100644 --- a/src/client/linters/baseLinter.ts +++ b/src/client/linters/baseLinter.ts @@ -30,6 +30,7 @@ export interface ILintMessage { type: string; severity?: LintMessageSeverity; provider: string; + messageContainsCode: boolean; } export enum LintMessageSeverity { Hint, @@ -163,7 +164,8 @@ export abstract class BaseLinter { column: isNaN(match.column) || match.column === 0 ? 0 : match.column - this.columnOffset, line: match.line, type: match.type, - provider: this.Id + provider: this.Id, + messageContainsCode: false }; } private parseLines(outputLines: string[], regEx: string): ILintMessage[] { diff --git a/src/client/linters/prospector.ts b/src/client/linters/prospector.ts index bfa2267d78e3..7e94db3f855e 100644 --- a/src/client/linters/prospector.ts +++ b/src/client/linters/prospector.ts @@ -52,7 +52,8 @@ export class Linter extends baseLinter.BaseLinter { column: msg.location.character, line: lineNumber, type: msg.code, - provider: `${this.Id} - ${msg.source}` + provider: `${this.Id} - ${msg.source}`, + messageContainsCode: false }; }); } diff --git a/src/client/linters/pylint.ts b/src/client/linters/pylint.ts index ae9a65a8c60a..161604d6da22 100644 --- a/src/client/linters/pylint.ts +++ b/src/client/linters/pylint.ts @@ -11,10 +11,23 @@ export class Linter extends baseLinter.BaseLinter { } protected async runLinter(document: TextDocument, cancellation: CancellationToken): Promise { - const msgTemplate = `'{line},{column},{category},${this.pythonSettings.linting.pylintMsgTemplate}'`; - const messages = await this.run([`--msg-template=${msgTemplate}`, '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation); + let msgBody; + let regex; + if (this.pythonSettings.linting.pylintMsgTemplate === 'legacy') { + msgBody = '{msg_id}:{msg}'; + } else if (this.pythonSettings.linting.pylintMsgTemplate === 'standard') { + msgBody = '{msg} ({symbol})'; + regex = '(?\\d+),(?\\d+),(?\\w+),(?[a-z-]+):(?.*)\\r?(\\n|$)'; + } + let codeVar = '{symbol}'; + if (msgBody.includes('{msg_id}') && !msgBody.includes('{symbol}')) { + codeVar = '{msg_id}'; + } + const msgTemplate = `'{line},{column},{category},${codeVar}:${msgBody}'`; + const messages = await this.run([`--msg-template=${msgTemplate}`, '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation, regex); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.pylintCategorySeverity); + msg.messageContainsCode = true; }); return messages; diff --git a/src/client/providers/lintProvider.ts b/src/client/providers/lintProvider.ts index 452bee68cdb3..916f3b9b5901 100644 --- a/src/client/providers/lintProvider.ts +++ b/src/client/providers/lintProvider.ts @@ -34,7 +34,13 @@ function createDiagnostics(message: linter.ILintMessage, document: vscode.TextDo const range = new vscode.Range(position, position); const severity = lintSeverityToVSSeverity.get(message.severity!)!; - const diagnostic = new vscode.Diagnostic(range, `${message.code}:${message.message}`, severity); + let formattedMessage; + if (message.messageContainsCode) { + formattedMessage = message.message; + } else { + formattedMessage = `${message.code}:${message.message}`; + } + const diagnostic = new vscode.Diagnostic(range, formattedMessage, severity); diagnostic.code = message.code; diagnostic.source = message.provider; return diagnostic; @@ -218,6 +224,7 @@ export class LintProvider implements vscode.Disposable { // Ignore magic commands from jupyter. if (hasJupyterCodeCells && document.lineAt(d.line - 1).text.trim().startsWith('%') && (d.code === LinterErrors.pylint.InvalidSyntax || + d.code === LinterErrors.pylint.InvalidSyntaxSymbolic || d.code === LinterErrors.prospector.InvalidSyntax || d.code === LinterErrors.flake8.InvalidSyntax)) { return; From c4917fba9566b5c2af725a4e47fea25ba8d65950 Mon Sep 17 00:00:00 2001 From: "J. Cliff Dyer" Date: Wed, 10 Jan 2018 10:18:13 -0500 Subject: [PATCH 4/4] Update tests to exercise both pylint formats. --- src/client/common/configSettings.ts | 2 +- src/client/linters/baseLinter.ts | 4 +- src/client/linters/pylint.ts | 2 +- src/client/providers/lintProvider.ts | 2 +- src/test/.vscode/settings.json | 2 +- src/test/common.ts | 2 +- src/test/debugger/portAndHost.test.ts | 12 ++-- src/test/linters/lint.test.ts | 91 ++++++++++++++++++--------- 8 files changed, 75 insertions(+), 42 deletions(-) diff --git a/src/client/common/configSettings.ts b/src/client/common/configSettings.ts index ed25cece3f92..8583c611315c 100644 --- a/src/client/common/configSettings.ts +++ b/src/client/common/configSettings.ts @@ -247,7 +247,7 @@ export class PythonSettings extends EventEmitter implements IPythonSettings { pylamaArgs: [], pylamaEnabled: false, pylamaPath: 'pylama', prospectorArgs: [], prospectorEnabled: false, prospectorPath: 'prospector', pydocstyleArgs: [], pydocstyleEnabled: false, pydocstylePath: 'pydocstyle', - pylintArgs: [], pylintEnabled: false, pylintPath: 'pylint', pylintMsgTemplate: '{msg_id}:{msg}', + pylintArgs: [], pylintEnabled: false, pylintPath: 'pylint', pylintMsgTemplate: 'legacy', pylintCategorySeverity: { convention: vscode.DiagnosticSeverity.Hint, error: vscode.DiagnosticSeverity.Error, diff --git a/src/client/linters/baseLinter.ts b/src/client/linters/baseLinter.ts index edac4b67a812..446f1d8d70ee 100644 --- a/src/client/linters/baseLinter.ts +++ b/src/client/linters/baseLinter.ts @@ -30,7 +30,7 @@ export interface ILintMessage { type: string; severity?: LintMessageSeverity; provider: string; - messageContainsCode: boolean; + preformattedMessage?: boolean; } export enum LintMessageSeverity { Hint, @@ -165,7 +165,7 @@ export abstract class BaseLinter { line: match.line, type: match.type, provider: this.Id, - messageContainsCode: false + preformattedMessage: false }; } private parseLines(outputLines: string[], regEx: string): ILintMessage[] { diff --git a/src/client/linters/pylint.ts b/src/client/linters/pylint.ts index 161604d6da22..b98442184aef 100644 --- a/src/client/linters/pylint.ts +++ b/src/client/linters/pylint.ts @@ -27,7 +27,7 @@ export class Linter extends baseLinter.BaseLinter { const messages = await this.run([`--msg-template=${msgTemplate}`, '--reports=n', '--output-format=text', document.uri.fsPath], document, cancellation, regex); messages.forEach(msg => { msg.severity = this.parseMessagesSeverity(msg.type, this.pythonSettings.linting.pylintCategorySeverity); - msg.messageContainsCode = true; + msg.preformattedMessage = true; }); return messages; diff --git a/src/client/providers/lintProvider.ts b/src/client/providers/lintProvider.ts index 916f3b9b5901..4955130c5996 100644 --- a/src/client/providers/lintProvider.ts +++ b/src/client/providers/lintProvider.ts @@ -35,7 +35,7 @@ function createDiagnostics(message: linter.ILintMessage, document: vscode.TextDo const severity = lintSeverityToVSSeverity.get(message.severity!)!; let formattedMessage; - if (message.messageContainsCode) { + if (message.preformattedMessage) { formattedMessage = message.message; } else { formattedMessage = `${message.code}:${message.message}`; diff --git a/src/test/.vscode/settings.json b/src/test/.vscode/settings.json index 12cde5b9dc53..dcfb904cf4f1 100644 --- a/src/test/.vscode/settings.json +++ b/src/test/.vscode/settings.json @@ -1,5 +1,5 @@ { - "python.linting.pylintEnabled": false, + "python.linting.pylintEnabled": true, "python.linting.flake8Enabled": false, "python.workspaceSymbols.enabled": false, "python.unitTest.nosetestArgs": [], diff --git a/src/test/common.ts b/src/test/common.ts index 702bb51679a1..1812305b9ce8 100644 --- a/src/test/common.ts +++ b/src/test/common.ts @@ -9,7 +9,7 @@ export const rootWorkspaceUri = getWorkspaceRoot(); export type PythonSettingKeys = 'workspaceSymbols.enabled' | 'pythonPath' | 'linting.lintOnSave' | - 'linting.enabled' | 'linting.pylintEnabled' | + 'linting.enabled' | 'linting.pylintEnabled' | 'linting.pylintMsgTemplate' | 'linting.flake8Enabled' | 'linting.pep8Enabled' | 'linting.pylamaEnabled' | 'linting.prospectorEnabled' | 'linting.pydocstyleEnabled' | 'linting.mypyEnabled' | 'unitTest.nosetestArgs' | 'unitTest.pyTestArgs' | 'unitTest.unittestArgs' | diff --git a/src/test/debugger/portAndHost.test.ts b/src/test/debugger/portAndHost.test.ts index a6d3ed23daac..76d3ced54da3 100644 --- a/src/test/debugger/portAndHost.test.ts +++ b/src/test/debugger/portAndHost.test.ts @@ -84,28 +84,28 @@ suite('Standard Debugging', () => { await debugClient.waitForEvent('terminated'); } - test('Confirm debuggig works if both port and host are not provided', async () => { + test('Confirm debugging works if both port and host are not provided', async () => { await testDebuggingWithProvidedPort(); }); - test('Confirm debuggig works if port=0', async () => { + test('Confirm debugging works if port=0', async () => { await testDebuggingWithProvidedPort(0, 'localhost'); }); - test('Confirm debuggig works if port=0 or host=localhost', async () => { + test('Confirm debugging works if port=0 or host=localhost', async () => { await testDebuggingWithProvidedPort(0, 'localhost'); }); - test('Confirm debuggig works if port=0 or host=127.0.0.1', async () => { + test('Confirm debugging works if port=0 or host=127.0.0.1', async () => { await testDebuggingWithProvidedPort(0, '127.0.0.1'); }); - test('Confirm debuggig fails when an invalid host is provided', async () => { + test('Confirm debugging fails when an invalid host is provided', async () => { const promise = testDebuggingWithProvidedPort(0, 'xyz123409924ple_ewf'); expect(promise).to.eventually.be.rejected.and.to.have.property('code', 'ENOTFOUND', 'Debugging failed for some other reason'); }); - test('Confirm debuggig fails when provided port is in use', async () => { + test('Confirm debugging fails when provided port is in use', async () => { // tslint:disable-next-line:no-empty const server = net.createServer((s) => { }); const port = await new Promise((resolve, reject) => server.listen({ host: 'localhost', port: 0 }, () => resolve(server.address().port))); diff --git a/src/test/linters/lint.test.ts b/src/test/linters/lint.test.ts index ddd6ef04f628..040979838e02 100644 --- a/src/test/linters/lint.test.ts +++ b/src/test/linters/lint.test.ts @@ -22,35 +22,59 @@ import { closeActiveWindows, initialize, initializeTest, IS_MULTI_ROOT_TEST } fr import { MockOutputChannel } from '../mockClasses'; import { UnitTestIocContainer } from '../unittests/serviceRegistry'; -const pythoFilesPath = path.join(__dirname, '..', '..', '..', 'src', 'test', 'pythonFiles', 'linting'); -const flake8ConfigPath = path.join(pythoFilesPath, 'flake8config'); -const pep8ConfigPath = path.join(pythoFilesPath, 'pep8config'); -const pydocstyleConfigPath27 = path.join(pythoFilesPath, 'pydocstyleconfig27'); -const pylintConfigPath = path.join(pythoFilesPath, 'pylintconfig'); -const fileToLint = path.join(pythoFilesPath, 'file.py'); +const pythonFilesPath = path.join(__dirname, '..', '..', '..', 'src', 'test', 'pythonFiles', 'linting'); +const flake8ConfigPath = path.join(pythonFilesPath, 'flake8config'); +const pep8ConfigPath = path.join(pythonFilesPath, 'pep8config'); +const pydocstyleConfigPath27 = path.join(pythonFilesPath, 'pydocstyleconfig27'); +const pylintConfigPath = path.join(pythonFilesPath, 'pylintconfig'); +const fileToLint = path.join(pythonFilesPath, 'file.py'); -const pylintMessagesToBeReturned: baseLinter.ILintMessage[] = [ - { line: 24, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 30, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 34, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, - { line: 40, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 44, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, - { line: 55, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 59, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'Locally enabling no-member (E1101)', provider: '', type: '' }, - { line: 62, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling undefined-variable (E0602)', provider: '', type: '' }, - { line: 70, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 84, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'Locally disabling no-member (E1101)', provider: '', type: '' }, - { line: 87, column: 0, severity: baseLinter.LintMessageSeverity.Hint, code: 'C0304', message: 'Final newline missing', provider: '', type: '' }, - { line: 11, column: 20, severity: baseLinter.LintMessageSeverity.Warning, code: 'W0613', message: 'Unused argument \'arg\'', provider: '', type: '' }, - { line: 26, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blop\' member', provider: '', type: '' }, - { line: 36, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 46, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 61, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 72, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 75, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 77, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' }, - { line: 83, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'Instance of \'Foo\' has no \'blip\' member', provider: '', type: '' } +const pylintLegacyMessagesToBeReturned: baseLinter.ILintMessage[] = [ + { line: 24, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'I0011:Locally disabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 30, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'I0011:Locally disabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 34, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'I0012:Locally enabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 40, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'I0011:Locally disabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 44, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'I0012:Locally enabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 55, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'I0011:Locally disabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 59, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0012', message: 'I0012:Locally enabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 62, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'I0011:Locally disabling undefined-variable (E0602)', provider: '', type: '', preformattedMessage: true }, + { line: 70, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'I0011:Locally disabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 84, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'I0011', message: 'I0011:Locally disabling no-member (E1101)', provider: '', type: '', preformattedMessage: true }, + { line: 87, column: 0, severity: baseLinter.LintMessageSeverity.Hint, code: 'C0304', message: 'C0304:Final newline missing', provider: '', type: '', preformattedMessage: true }, + { line: 11, column: 20, severity: baseLinter.LintMessageSeverity.Warning, code: 'W0613', message: 'W0613:Unused argument \'arg\'', provider: '', type: '', preformattedMessage: true }, + { line: 26, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blop\' member', provider: '', type: '', preformattedMessage: true }, + { line: 36, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blip\' member', provider: '', type: '', preformattedMessage: true }, + { line: 46, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blip\' member', provider: '', type: '', preformattedMessage: true }, + { line: 61, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blip\' member', provider: '', type: '', preformattedMessage: true }, + { line: 72, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blip\' member', provider: '', type: '', preformattedMessage: true }, + { line: 75, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blip\' member', provider: '', type: '', preformattedMessage: true }, + { line: 77, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blip\' member', provider: '', type: '', preformattedMessage: true }, + { line: 83, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'E1101', message: 'E1101:Instance of \'Foo\' has no \'blip\' member', provider: '', type: '', preformattedMessage: true } +]; + +const pylintStandardMessagesToBeReturned: baseLinter.ILintMessage[] = [ + { line: 24, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'disable-no-member', message: 'Locally disabling no-member (E1101) (disable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 30, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'disable-no-member', message: 'Locally disabling no-member (E1101) (disable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 34, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'enable-no-member', message: 'Locally enabling no-member (E1101) (enable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 40, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'disable-no-member', message: 'Locally disabling no-member (E1101) (disable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 44, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'enable-no-member', message: 'Locally enabling no-member (E1101) (enable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 55, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'disable-no-member', message: 'Locally disabling no-member (E1101) (disable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 59, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'enable-no-member', message: 'Locally enabling no-member (E1101) (enable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 62, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'disable-no-member', message: 'Locally disabling undefined-variable (E0602) (disable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 70, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'disable-no-member', message: 'Locally disabling no-member (E1101) (disable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 84, column: 0, severity: baseLinter.LintMessageSeverity.Information, code: 'disable-no-member', message: 'Locally disabling no-member (E1101) (disable-no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 87, column: 0, severity: baseLinter.LintMessageSeverity.Hint, code: 'missing-newline', message: 'Final newline missing (missing-newline)', provider: '', type: '', preformattedMessage: true }, + { line: 11, column: 20, severity: baseLinter.LintMessageSeverity.Warning, code: 'unused-argument', message: 'Unused argument \'arg\' (unused-argument)', provider: '', type: '', preformattedMessage: true }, + { line: 26, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blop\' member (no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 36, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blip\' member (no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 46, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blip\' member (no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 61, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blip\' member (no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 72, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blip\' member (no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 75, column: 18, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blip\' member (no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 77, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blip\' member (no-member)', provider: '', type: '', preformattedMessage: true }, + { line: 83, column: 14, severity: baseLinter.LintMessageSeverity.Error, code: 'no-member', message: 'Instance of \'Foo\' has no \'blip\' member (no-member)', provider: '', type: '', preformattedMessage: true } ]; + const flake8MessagesToBeReturned: baseLinter.ILintMessage[] = [ { line: 5, column: 1, severity: baseLinter.LintMessageSeverity.Error, code: 'E302', message: 'expected 2 blank lines, found 1', provider: '', type: '' }, { line: 19, column: 15, severity: baseLinter.LintMessageSeverity.Error, code: 'E127', message: 'continuation line over-indented for visual indent', provider: '', type: '' }, @@ -271,9 +295,18 @@ suite('Linting', () => { } } } - test('PyLint', async () => { - await testLinterMessages(Product.pylint, fileToLint, pylintMessagesToBeReturned); + test('PyLint Default Output is Legacy', async () => { + await testLinterMessages(Product.pylint, fileToLint, pylintLegacyMessagesToBeReturned); }); + test('PyLint Legacy Output', async () => { + await updateSetting('linting.pylintMsgTemplate', 'legacy', rootWorkspaceUri, IS_MULTI_ROOT_TEST ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Workspace); + await testLinterMessages(Product.pylint, fileToLint, pylintLegacyMessagesToBeReturned); + }); + test('PyLint Standard Output', async () => { + await updateSetting('linting.pylintMsgTemplate', 'standard', rootWorkspaceUri, IS_MULTI_ROOT_TEST ? vscode.ConfigurationTarget.WorkspaceFolder : vscode.ConfigurationTarget.Workspace); + await testLinterMessages(Product.pylint, fileToLint, pylintStandardMessagesToBeReturned); + }); + test('Flake8', async () => { await testLinterMessages(Product.flake8, fileToLint, flake8MessagesToBeReturned); });