Skip to content

Commit 542477d

Browse files
authored
Auto lint opened files and re-lint upon config changes (#15)
* auto lint opened files and re-lint upon config changes * fix linter
1 parent 618ac54 commit 542477d

File tree

2 files changed

+117
-1
lines changed

2 files changed

+117
-1
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { EventEmitter } from 'events';
2+
import { ConfigurationTarget, Disposable, Uri, workspace, WorkspaceFolder } from 'vscode';
3+
import { PythonSettings } from '../common/configSettings';
4+
5+
type settingsToMonitor = 'linting';
6+
7+
export class ConfigSettingMonitor extends EventEmitter implements Disposable {
8+
private oldSettings = new Map<string, string>();
9+
// tslint:disable-next-line:no-any
10+
private timeout?: any;
11+
constructor(private settingToMonitor: settingsToMonitor) {
12+
super();
13+
this.initializeSettings();
14+
// tslint:disable-next-line:no-void-expression
15+
PythonSettings.getInstance().on('change', () => this.onConfigChange());
16+
}
17+
public dispose() {
18+
if (this.timeout) {
19+
// tslint:disable-next-line:no-unsafe-any
20+
clearTimeout(this.timeout);
21+
}
22+
}
23+
private onConfigChange() {
24+
if (this.timeout) {
25+
// tslint:disable-next-line:no-unsafe-any
26+
clearTimeout(this.timeout);
27+
}
28+
this.timeout = setTimeout(() => {
29+
this.timeout = undefined;
30+
this.checkChangesToSettingsInWorkspace();
31+
this.checkChangesToSettingsInWorkspaceFolders();
32+
}, 1000);
33+
}
34+
private initializeSettings() {
35+
if (!Array.isArray(workspace.workspaceFolders)) {
36+
return;
37+
}
38+
if (workspace.workspaceFolders.length === 1) {
39+
const key = this.getWorkspaceKey();
40+
const currentValue = JSON.stringify(PythonSettings.getInstance()[this.settingToMonitor]);
41+
this.oldSettings.set(key, currentValue);
42+
} else {
43+
workspace.workspaceFolders.forEach(wkspaceFolder => {
44+
const key = this.getWorkspaceFolderKey(wkspaceFolder.uri);
45+
const currentValue = JSON.stringify(PythonSettings.getInstance(wkspaceFolder.uri)[this.settingToMonitor]);
46+
this.oldSettings.set(key, currentValue);
47+
});
48+
}
49+
}
50+
private checkChangesToSettingsInWorkspace() {
51+
if (!Array.isArray(workspace.workspaceFolders) || workspace.workspaceFolders.length === 0) {
52+
return;
53+
}
54+
const newValue = JSON.stringify(PythonSettings.getInstance()[this.settingToMonitor]);
55+
this.checkChangesAndNotifiy(ConfigurationTarget.Workspace, workspace.workspaceFolders[0].uri, newValue);
56+
}
57+
private checkChangesToSettingsInWorkspaceFolders() {
58+
if (!Array.isArray(workspace.workspaceFolders) || workspace.workspaceFolders.length <= 1) {
59+
return;
60+
}
61+
// tslint:disable-next-line:no-void-expression
62+
workspace.workspaceFolders.forEach(folder => this.checkChangesToSettingsInWorkspaceFolder(folder));
63+
}
64+
private checkChangesToSettingsInWorkspaceFolder(workspaceFolder: WorkspaceFolder) {
65+
const newValue = JSON.stringify(PythonSettings.getInstance(workspaceFolder.uri)[this.settingToMonitor]);
66+
this.checkChangesAndNotifiy(ConfigurationTarget.WorkspaceFolder, workspaceFolder.uri, newValue);
67+
}
68+
private checkChangesAndNotifiy(configTarget: ConfigurationTarget, uri: Uri, newValue: string) {
69+
const key = configTarget === ConfigurationTarget.Workspace ? this.getWorkspaceKey() : this.getWorkspaceFolderKey(uri);
70+
if (this.oldSettings.has(key)) {
71+
const oldValue = this.oldSettings.get(key);
72+
if (oldValue !== newValue) {
73+
this.oldSettings.set(key, newValue);
74+
this.emit('change', configTarget, uri);
75+
}
76+
} else {
77+
this.oldSettings.set(key, newValue);
78+
}
79+
}
80+
private getWorkspaceKey() {
81+
// tslint:disable-next-line:no-non-null-assertion
82+
return workspace.workspaceFolders[0]!.uri.fsPath;
83+
}
84+
private getWorkspaceFolderKey(wkspaceFolder: Uri) {
85+
return `${ConfigurationTarget.WorkspaceFolder}:${wkspaceFolder.fsPath}`;
86+
}
87+
}

src/client/providers/lintProvider.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
import * as fs from 'fs';
44
import * as path from 'path';
55
import * as vscode from 'vscode';
6+
import { ConfigurationTarget, Uri, workspace } from 'vscode';
7+
import { ConfigSettingMonitor } from '../common/configSettingMonitor';
68
import { PythonSettings } from '../common/configSettings';
79
import { LinterErrors } from '../common/constants';
10+
import { PythonLanguage } from '../jupyter/common/constants';
811
import * as linter from '../linters/baseLinter';
912
import { sendTelemetryWhenDone } from '../telemetry';
1013
import { LINTING } from '../telemetry/constants';
@@ -49,18 +52,22 @@ export class LintProvider implements vscode.Disposable {
4952
private outputChannel: vscode.OutputChannel;
5053
private context: vscode.ExtensionContext;
5154
private disposables: vscode.Disposable[];
55+
private configMonitor: ConfigSettingMonitor;
5256
public constructor(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel,
5357
public documentHasJupyterCodeCells: DocumentHasJupyterCodeCells) {
5458
this.outputChannel = outputChannel;
5559
this.context = context;
5660
this.disposables = [];
5761
this.initialize();
62+
this.configMonitor = new ConfigSettingMonitor('linting');
63+
this.configMonitor.on('change', this.lintSettingsChangedHandler.bind(this));
5864
}
5965
public dispose() {
6066
this.disposables.forEach(d => d.dispose());
67+
this.configMonitor.dispose();
6168
}
6269
private isDocumentOpen(uri: vscode.Uri): boolean {
63-
return vscode.window.visibleTextEditors.some(editor => editor.document && editor.document.uri.fsPath === uri.fsPath);
70+
return vscode.workspace.textDocuments.some(document => document.uri.fsPath === uri.fsPath);
6471
}
6572

6673
private initialize() {
@@ -109,6 +116,28 @@ export class LintProvider implements vscode.Disposable {
109116
}
110117
});
111118
this.context.subscriptions.push(disposable);
119+
this.lintOpenPythonFiles();
120+
}
121+
122+
private lintOpenPythonFiles() {
123+
workspace.textDocuments.forEach(document => {
124+
if (document.languageId === PythonLanguage.language) {
125+
this.onLintDocument(document, 'auto');
126+
}
127+
});
128+
}
129+
private lintSettingsChangedHandler(configTarget: ConfigurationTarget, wkspaceOrFolder: Uri) {
130+
if (configTarget === ConfigurationTarget.Workspace) {
131+
this.lintOpenPythonFiles();
132+
return;
133+
}
134+
// Look for python files that belong to the specified workspace folder.
135+
workspace.textDocuments.forEach(document => {
136+
const wkspaceFolder = workspace.getWorkspaceFolder(document.uri);
137+
if (wkspaceFolder && wkspaceFolder.uri.fsPath === wkspaceOrFolder.fsPath) {
138+
this.onLintDocument(document, 'auto');
139+
}
140+
});
112141
}
113142

114143
// tslint:disable-next-line:member-ordering

0 commit comments

Comments
 (0)