diff --git a/src/client/common/serviceRegistry.ts b/src/client/common/serviceRegistry.ts index 8ac2689adcba..5417d71f7e30 100644 --- a/src/client/common/serviceRegistry.ts +++ b/src/client/common/serviceRegistry.ts @@ -28,5 +28,4 @@ export function registerTypes(serviceManager: IServiceManager) { serviceManager.addSingleton(IApplicationShell, ApplicationShell); serviceManager.addSingleton(ICurrentProcess, CurrentProcess); serviceManager.addSingleton(IInstaller, Installer); - serviceManager.addSingleton(IFileSystem, FileSystem); } diff --git a/src/client/formatters/helper.ts b/src/client/formatters/helper.ts index 69aa540385bb..579fbdc7772e 100644 --- a/src/client/formatters/helper.ts +++ b/src/client/formatters/helper.ts @@ -38,10 +38,10 @@ export class FormatterHelper implements IFormatterHelper { // If path information is not available, then treat it as a module, // except for prospector as that needs to be run as an executable (it's a Python package). - if (path.basename(execPath) === execPath && formatter !== Product.prospector) { + if (path.basename(execPath) === execPath) { moduleName = execPath; } - return { execPath, moduleName, args }; + return { execPath, moduleName, args, product: formatter }; } } diff --git a/src/client/linters/helper.ts b/src/client/linters/helper.ts index 7a2f9bb96a92..c5c5b3ce1014 100644 --- a/src/client/linters/helper.ts +++ b/src/client/linters/helper.ts @@ -35,7 +35,7 @@ export class LinterHelper implements ILinterHelper { moduleName = execPath; } - return { execPath, moduleName, args }; + return { execPath, moduleName, args, product: linter }; } public translateToId(linter: Product): LinterId { if (this.linterIdMapping.has(linter)) { diff --git a/src/test/format/format.helper.test.ts b/src/test/format/format.helper.test.ts new file mode 100644 index 000000000000..8c04be616b33 --- /dev/null +++ b/src/test/format/format.helper.test.ts @@ -0,0 +1,88 @@ +import * as assert from 'assert'; +import * as path from 'path'; +import { IFormattingSettings, PythonSettings } from '../../client/common/configSettings'; +import { EnumEx } from '../../client/common/enumUtils'; +import { Product } from '../../client/common/types'; +import { FormatterHelper } from '../../client/formatters/helper'; +import { FormatterId } from '../../client/formatters/types'; +import { initialize } from '../initialize'; + +// tslint:disable-next-line:max-func-body-length +suite('Formatting - Helper', () => { + const formatHelper = new FormatterHelper(); + suiteSetup(initialize); + + test('Ensure product is set in Execution Info', async () => { + [Product.autopep8, Product.yapf].forEach(formatter => { + const info = formatHelper.getExecutionInfo(formatter, []); + assert.equal(info.product, formatter, `Incorrect products for ${formatHelper.translateToId(formatter)}`); + }); + }); + + test('Ensure executable is set in Execution Info', async () => { + const settings = PythonSettings.getInstance(); + + [Product.autopep8, Product.yapf].forEach(formatter => { + const info = formatHelper.getExecutionInfo(formatter, []); + const names = formatHelper.getSettingsPropertyNames(formatter); + const execPath = settings.formatting[names.pathName] as string; + let moduleName: string | undefined; + if (path.basename(execPath) === execPath) { + moduleName = execPath; + } + + assert.equal(info.execPath, execPath, `Incorrect executable paths for product ${formatHelper.translateToId(formatter)}`); + }); + }); + + test('Ensure arguments are set in Execution Info', async () => { + const settings = PythonSettings.getInstance(); + const customArgs = ['1', '2', '3']; + + [Product.autopep8, Product.yapf].forEach(formatter => { + const info = formatHelper.getExecutionInfo(formatter, []); + const names = formatHelper.getSettingsPropertyNames(formatter); + const args: string[] = Array.isArray(settings.formatting[names.argsName]) ? settings.formatting[names.argsName] as string[] : []; + const expectedArgs = args.concat(customArgs).join(','); + + assert.equal(expectedArgs.endsWith(customArgs.join(',')), true, `Incorrect custom arguments for product ${formatHelper.translateToId(formatter)}`); + + }); + }); + + test('Ensure correct setting names are returned', async () => { + [Product.autopep8, Product.yapf].forEach(formatter => { + const translatedId = formatHelper.translateToId(formatter)!; + const settings = { + argsName: `${translatedId}Args` as keyof IFormattingSettings, + pathName: `${translatedId}Path` as keyof IFormattingSettings + }; + + assert.deepEqual(formatHelper.getSettingsPropertyNames(formatter), settings, `Incorrect settings for product ${formatHelper.translateToId(formatter)}`); + }); + }); + + test('Ensure translation of ids works', async () => { + const formatterMapping = new Map(); + formatterMapping.set(Product.autopep8, 'autopep8'); + formatterMapping.set(Product.yapf, 'yapf'); + + [Product.autopep8, Product.yapf].forEach(formatter => { + const translatedId = formatHelper.translateToId(formatter); + assert.equal(translatedId, formatterMapping.get(formatter)!, `Incorrect translation for product ${formatHelper.translateToId(formatter)}`); + }); + }); + + EnumEx.getValues(Product).forEach(product => { + const formatterMapping = new Map(); + formatterMapping.set(Product.autopep8, 'autopep8'); + formatterMapping.set(Product.yapf, 'yapf'); + if (formatterMapping.has(product)) { + return; + } + + test(`Ensure translation of ids throws exceptions for unknown formatters (${product})`, async () => { + assert.throws(() => formatHelper.translateToId(product)); + }); + }); +}); diff --git a/src/test/linters/lint.helper.test.ts b/src/test/linters/lint.helper.test.ts new file mode 100644 index 000000000000..c9bbb4cc68cf --- /dev/null +++ b/src/test/linters/lint.helper.test.ts @@ -0,0 +1,104 @@ +import * as assert from 'assert'; +import * as path from 'path'; +import { ILintingSettings, PythonSettings } from '../../client/common/configSettings'; +import { EnumEx } from '../../client/common/enumUtils'; +import { Product } from '../../client/common/types'; +import { LinterHelper } from '../../client/linters/helper'; +import { LinterId } from '../../client/linters/types'; +import { initialize } from '../initialize'; + +// tslint:disable-next-line:max-func-body-length +suite('Linting - Helper', () => { + const linterHelper = new LinterHelper(); + suiteSetup(initialize); + + test('Ensure product is set in Execution Info', async () => { + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { + const info = linterHelper.getExecutionInfo(linter, []); + assert.equal(info.product, linter, `Incorrect products for ${linterHelper.translateToId(linter)}`); + }); + }); + + test('Ensure executable is set in Execution Info', async () => { + const settings = PythonSettings.getInstance(); + + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { + const info = linterHelper.getExecutionInfo(linter, []); + const names = linterHelper.getSettingsPropertyNames(linter); + const execPath = settings.linting[names.pathName] as string; + let moduleName: string | undefined; + if (path.basename(execPath) === execPath && linter !== Product.prospector) { + moduleName = execPath; + } + + assert.equal(info.execPath, execPath, `Incorrect executable paths for product ${linterHelper.translateToId(linter)}`); + }); + }); + + test('Ensure arguments are set in Execution Info', async () => { + const settings = PythonSettings.getInstance(); + const customArgs = ['1', '2', '3']; + + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { + const info = linterHelper.getExecutionInfo(linter, []); + const names = linterHelper.getSettingsPropertyNames(linter); + const args: string[] = Array.isArray(settings.linting[names.argsName]) ? settings.linting[names.argsName] as string[] : []; + const expectedArgs = args.concat(customArgs).join(','); + + assert.equal(expectedArgs.endsWith(customArgs.join(',')), true, `Incorrect custom arguments for product ${linterHelper.translateToId(linter)}`); + + }); + }); + + test('Ensure correct setting names are returned', async () => { + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { + const translatedId = linterHelper.translateToId(linter)!; + const settings = { + argsName: `${translatedId}Args` as keyof ILintingSettings, + pathName: `${translatedId}Path` as keyof ILintingSettings, + enabledName: `${translatedId}Enabled` as keyof ILintingSettings + }; + + assert.deepEqual(linterHelper.getSettingsPropertyNames(linter), settings, `Incorrect settings for product ${linterHelper.translateToId(linter)}`); + }); + }); + + test('Ensure translation of ids works', async () => { + const linterIdMapping = new Map(); + linterIdMapping.set(Product.flake8, 'flake8'); + linterIdMapping.set(Product.mypy, 'mypy'); + linterIdMapping.set(Product.pep8, 'pep8'); + linterIdMapping.set(Product.prospector, 'prospector'); + linterIdMapping.set(Product.pydocstyle, 'pydocstyle'); + linterIdMapping.set(Product.pylama, 'pylama'); + linterIdMapping.set(Product.pylint, 'pylint'); + + [Product.flake8, Product.mypy, Product.pep8, + Product.pydocstyle, Product.pylama, Product.pylint].forEach(linter => { + const translatedId = linterHelper.translateToId(linter); + assert.equal(translatedId, linterIdMapping.get(linter)!, `Incorrect translation for product ${linterHelper.translateToId(linter)}`); + }); + }); + + EnumEx.getValues(Product).forEach(product => { + const linterIdMapping = new Map(); + linterIdMapping.set(Product.flake8, 'flake8'); + linterIdMapping.set(Product.mypy, 'mypy'); + linterIdMapping.set(Product.pep8, 'pep8'); + linterIdMapping.set(Product.prospector, 'prospector'); + linterIdMapping.set(Product.pydocstyle, 'pydocstyle'); + linterIdMapping.set(Product.pylama, 'pylama'); + linterIdMapping.set(Product.pylint, 'pylint'); + if (linterIdMapping.has(product)) { + return; + } + + test(`Ensure translation of ids throws exceptions for unknown linters (${product})`, async () => { + assert.throws(() => linterHelper.translateToId(product)); + }); + }); +});