Skip to content

Commit

Permalink
Disable linter without workspaces (microsoft#241)
Browse files Browse the repository at this point in the history
* Fix microsoft/vscode#37627 (microsoft#1368)

* Version 0.7.0 of extension (microsoft#1381)

Archive of 0.7.0

* Update README.md

* Update README.md

* fix readme

* fixes #42 disable in workspace specific config
  • Loading branch information
DonJayamanne committed Nov 16, 2017
1 parent 7b0838b commit f9e2596
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 22 deletions.
27 changes: 16 additions & 11 deletions src/client/common/installer.ts
@@ -1,9 +1,8 @@
import * as os from 'os';
import * as vscode from 'vscode';
import { commands, ConfigurationTarget, Disposable, OutputChannel, Terminal, Uri, window, workspace } from 'vscode';
import { ConfigurationTarget, Uri, window, workspace } from 'vscode';
import * as settings from './configSettings';
import { isNotInstalledError } from './helpers';
import { error } from './logger';
import { execPythonFile, getFullyQualifiedPythonInterpreterPath, IS_WINDOWS } from './utils';

export enum Product {
Expand Down Expand Up @@ -203,12 +202,13 @@ export class Installer implements vscode.Disposable {
return InstallerResponse.Ignore;
}

const installOption = ProductInstallationPrompt.has(product) ? ProductInstallationPrompt.get(product) : `Install ${productName}`;
// tslint:disable-next-line:no-non-null-assertion
const installOption = ProductInstallationPrompt.has(product) ? ProductInstallationPrompt.get(product)! : `Install ${productName}`;
const disableOption = `Disable ${productTypeName}`;
const dontShowAgain = 'Don\'t show this prompt again';
const alternateFormatter = product === Product.autopep8 ? 'yapf' : 'autopep8';
const useOtherFormatter = `Use '${alternateFormatter}' formatter`;
const options = [];
const options: string[] = [];
options.push(installOption);
if (productType === ProductType.Formatter) {
options.push(...[useOtherFormatter]);
Expand All @@ -217,6 +217,9 @@ export class Installer implements vscode.Disposable {
options.push(...[disableOption, dontShowAgain]);
}
const item = await window.showErrorMessage(`${productTypeName} ${productName} is not installed`, ...options);
if (!item) {
return InstallerResponse.Ignore;
}
switch (item) {
case installOption: {
return this.install(product, resource);
Expand Down Expand Up @@ -313,26 +316,28 @@ export class Installer implements vscode.Disposable {
}

return installationPromise
.then(() => this.isInstalled(product))
.then(async () => this.isInstalled(product))
.then(isInstalled => isInstalled ? InstallerResponse.Installed : InstallerResponse.Ignore);
}

// tslint:disable-next-line:member-ordering
public isInstalled(product: Product, resource?: Uri): Promise<boolean | undefined> {
public async isInstalled(product: Product, resource?: Uri): Promise<boolean | undefined> {
return isProductInstalled(product, resource);
}

// tslint:disable-next-line:member-ordering no-any
public uninstall(product: Product, resource?: Uri): Promise<any> {
public async uninstall(product: Product, resource?: Uri): Promise<any> {
return uninstallproduct(product, resource);
}
// tslint:disable-next-line:member-ordering
public disableLinter(product: Product, resource: Uri) {
if (resource && !workspace.getWorkspaceFolder(resource)) {
public async disableLinter(product: Product, resource?: Uri) {
if (resource && workspace.getWorkspaceFolder(resource)) {
// tslint:disable-next-line:no-non-null-assertion
const settingToDisable = SettingToDisableProduct.get(product)!;
const pythonConfig = workspace.getConfiguration('python', resource);
return pythonConfig.update(settingToDisable, false, ConfigurationTarget.Workspace);
const isMultiroot = Array.isArray(workspace.workspaceFolders) && workspace.workspaceFolders.length > 1;
const configTarget = isMultiroot ? ConfigurationTarget.WorkspaceFolder : ConfigurationTarget.Workspace;
return pythonConfig.update(settingToDisable, false, configTarget);
} else {
const pythonConfig = workspace.getConfiguration('python');
return pythonConfig.update('linting.enabledWithoutWorkspace', false, true);
Expand Down Expand Up @@ -382,7 +387,7 @@ async function isProductInstalled(product: Product, resource?: Uri): Promise<boo
}

// tslint:disable-next-line:no-any
function uninstallproduct(product: Product, resource?: Uri): Promise<any> {
async function uninstallproduct(product: Product, resource?: Uri): Promise<any> {
if (!ProductUninstallScripts.has(product)) {
return Promise.resolve();
}
Expand Down
15 changes: 9 additions & 6 deletions src/test/common.ts
Expand Up @@ -14,9 +14,10 @@ export type PythonSettingKeys = 'workspaceSymbols.enabled' | 'pythonPath' |
'linting.prospectorEnabled' | 'linting.pydocstyleEnabled' | 'linting.mypyEnabled' |
'unitTest.nosetestArgs' | 'unitTest.pyTestArgs' | 'unitTest.unittestArgs' |
'formatting.formatOnSave' | 'formatting.provider' | 'sortImports.args' |
'unitTest.nosetestsEnabled' | 'unitTest.pyTestEnabled' | 'unitTest.unittestEnabled';
'unitTest.nosetestsEnabled' | 'unitTest.pyTestEnabled' | 'unitTest.unittestEnabled' |
'linting.enabledWithoutWorkspace';

export async function updateSetting(setting: PythonSettingKeys, value: {}, resource: Uri, configTarget: ConfigurationTarget) {
export async function updateSetting(setting: PythonSettingKeys, value: {}, resource: Uri | undefined, configTarget: ConfigurationTarget) {
const settings = workspace.getConfiguration('python', resource);
const currentValue = settings.inspect(setting);
if (currentValue !== undefined && ((configTarget === ConfigurationTarget.Global && currentValue.globalValue === value) ||
Expand Down Expand Up @@ -50,8 +51,7 @@ export function retryAsync(wrapped: Function, retryCount: number = 2) {
const reasons: any[] = [];

const makeCall = () => {
// tslint:disable-next-line:no-unsafe-any no-any
// tslint:disable-next-line:no-invalid-this
// tslint:disable-next-line:no-unsafe-any no-any no-invalid-this
wrapped.call(this, ...args)
// tslint:disable-next-line:no-unsafe-any no-any
.then(resolve, (reason: any) => {
Expand Down Expand Up @@ -86,7 +86,9 @@ async function setPythonPathInWorkspace(resource: string | Uri | undefined, conf
}
async function restoreGlobalPythonPathSetting(): Promise<void> {
const pythonConfig = workspace.getConfiguration('python');
const currentGlobalPythonPathSetting = pythonConfig.inspect('pythonPath').globalValue;
// tslint:disable-next-line:no-non-null-assertion
const currentGlobalPythonPathSetting = pythonConfig.inspect('pythonPath')!.globalValue;
// tslint:disable-next-line:no-use-before-declare
if (globalPythonPathSetting !== currentGlobalPythonPathSetting) {
await pythonConfig.update('pythonPath', undefined, true);
}
Expand All @@ -106,7 +108,8 @@ export async function deleteFile(file: string) {
}
}

const globalPythonPathSetting = workspace.getConfiguration('python').inspect('pythonPath').globalValue;
// tslint:disable-next-line:no-non-null-assertion
const globalPythonPathSetting = workspace.getConfiguration('python').inspect('pythonPath')!.globalValue;
export const clearPythonPathInWorkspaceFolder = async (resource: string | Uri) => retryAsync(setPythonPathInWorkspace)(resource, ConfigurationTarget.WorkspaceFolder);
export const setPythonPathInWorkspaceRoot = async (pythonPath: string) => retryAsync(setPythonPathInWorkspace)(undefined, ConfigurationTarget.Workspace, pythonPath);
export const resetGlobalPythonPathSetting = async () => retryAsync(restoreGlobalPythonPathSetting)();
58 changes: 58 additions & 0 deletions src/test/common/installer.multiroot.test.ts
@@ -0,0 +1,58 @@
import * as assert from 'assert';
import * as path from 'path';
import { ConfigurationTarget, Uri, workspace } from 'vscode';
import { Installer, Product } from '../../client/common/installer';
import { rootWorkspaceUri } from '../common';
import { updateSetting } from '../common';
import { closeActiveWindows, initializeTest, IS_MULTI_ROOT_TEST } from './../initialize';
import { MockOutputChannel } from './../mockClasses';

// tslint:disable-next-line:no-suspicious-comment
// TODO: Need to mock the command runner, to check what commands are being sent.
// Instead of altering the environment.

suite('Installer', () => {
let outputChannel: MockOutputChannel;
let installer: Installer;
const workspaceUri = Uri.file(path.join(__dirname, '..', '..', '..', 'src', 'test'));
suiteSetup(async function () {
if (!IS_MULTI_ROOT_TEST) {
// tslint:disable-next-line:no-invalid-this
this.skip();
}
outputChannel = new MockOutputChannel('Installer');
installer = new Installer(outputChannel);
await initializeTest();
});
setup(async () => {
await initializeTest();
await resetSettings();
});
suiteTeardown(async () => {
await closeActiveWindows();
await resetSettings();
});
teardown(closeActiveWindows);

async function resetSettings() {
await updateSetting('linting.enabledWithoutWorkspace', true, undefined, ConfigurationTarget.Global);
await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace);
if (IS_MULTI_ROOT_TEST) {
await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.WorkspaceFolder);
}
}

test('Disable linting of files contained in a multi-root workspace', async function () {
if (!IS_MULTI_ROOT_TEST) {
// tslint:disable-next-line:no-invalid-this
this.skip();
}
await installer.disableLinter(Product.pylint, workspaceUri);
const pythonWConfig = workspace.getConfiguration('python', workspaceUri);
const value = pythonWConfig.inspect<boolean>('linting.pylintEnabled');
// tslint:disable-next-line:no-non-null-assertion
assert.equal(value!.workspaceValue, true, 'Workspace setting has been disabled');
// tslint:disable-next-line:no-non-null-assertion
assert.equal(value!.workspaceFolderValue, false, 'Workspace folder setting not disabled');
});
});
40 changes: 35 additions & 5 deletions src/test/common/installer.test.ts
@@ -1,11 +1,14 @@
import * as assert from 'assert';
import * as path from 'path';
import { Uri } from 'vscode';
import { ConfigurationTarget, Uri, workspace } from 'vscode';
import { EnumEx } from '../../client/common/enumUtils';
import { Installer, Product } from '../../client/common/installer';
import { rootWorkspaceUri } from '../common';
import { updateSetting } from '../common';
import { closeActiveWindows, initializeTest, IS_MULTI_ROOT_TEST, IS_TRAVIS } from './../initialize';
import { MockOutputChannel } from './../mockClasses';

// tslint:disable-next-line:no-suspicious-comment
// TODO: Need to mock the command runner, to check what commands are being sent.
// Instead of altering the environment.

Expand All @@ -19,16 +22,27 @@ suite('Installer', () => {
installer = new Installer(outputChannel);
await initializeTest();
});
setup(initializeTest);
suiteTeardown(closeActiveWindows);
setup(async () => {
await initializeTest();
await resetSettings();
});
suiteTeardown(async () => {
await closeActiveWindows();
await resetSettings();
});
teardown(closeActiveWindows);

async function resetSettings() {
await updateSetting('linting.enabledWithoutWorkspace', true, undefined, ConfigurationTarget.Global);
await updateSetting('linting.pylintEnabled', true, rootWorkspaceUri, ConfigurationTarget.Workspace);
}

async function testUninstallingProduct(product: Product) {
let isInstalled = await installer.isInstalled(product, resource);
if (isInstalled) {
await installer.uninstall(product, resource);
isInstalled = await installer.isInstalled(product, resource);
// Someimtes installation doesn't work on Travis
// Sometimes installation doesn't work on Travis
if (!IS_TRAVIS) {
assert.equal(isInstalled, false, 'Product uninstall failed');
}
Expand All @@ -50,7 +64,7 @@ suite('Installer', () => {
await installer.install(product, resource);
}
const checkIsInstalledAgain = await installer.isInstalled(product, resource);
// Someimtes installation doesn't work on Travis
// Sometimes installation doesn't work on Travis
if (!IS_TRAVIS) {
assert.notEqual(checkIsInstalledAgain, false, 'Product installation failed');
}
Expand All @@ -63,4 +77,20 @@ suite('Installer', () => {
await testInstallingProduct(prod.value);
});
});

test('Disable linting of files not contained in a workspace', async () => {
await installer.disableLinter(Product.pylint, undefined);
const pythonConfig = workspace.getConfiguration('python');
assert.equal(pythonConfig.get<boolean>('linting.enabledWithoutWorkspace'), false, 'Incorrect setting');
});

test('Disable linting of files contained in a workspace', async function () {
if (IS_MULTI_ROOT_TEST) {
// tslint:disable-next-line:no-invalid-this
this.skip();
}
await installer.disableLinter(Product.pylint, workspaceUri);
const pythonConfig = workspace.getConfiguration('python', workspaceUri);
assert.equal(pythonConfig.get<boolean>('linting.pylintEnabled'), false, 'Incorrect setting');
});
});
1 change: 1 addition & 0 deletions tslint.json
Expand Up @@ -43,6 +43,7 @@
"PromiseLike"
],
"completed-docs": false,
"no-backbone-get-set-outside-model": false,
"no-unsafe-any": false
}
}

0 comments on commit f9e2596

Please sign in to comment.