|
13 | 13 | //===----------------------------------------------------------------------===//
|
14 | 14 |
|
15 | 15 | import * as vscode from "vscode";
|
16 |
| -import * as path from "path"; |
17 |
| -import { isPathInsidePath } from "./utilities/filesystem"; |
18 | 16 | import { getBuildAllTask } from "./tasks/SwiftTaskProvider";
|
19 | 17 | import configuration from "./configuration";
|
20 | 18 | import { FolderContext } from "./FolderContext";
|
21 |
| -import { WorkspaceContext } from "./WorkspaceContext"; |
22 | 19 | import { TaskOperation } from "./tasks/TaskQueue";
|
| 20 | +// eslint-disable-next-line @typescript-eslint/no-require-imports |
| 21 | +import debounce = require("lodash.debounce"); |
23 | 22 |
|
24 |
| -export class BackgroundCompilation { |
25 |
| - private waitingToRun = false; |
| 23 | +export class BackgroundCompilation implements vscode.Disposable { |
| 24 | + private workspaceFileWatcher?: vscode.FileSystemWatcher; |
| 25 | + private configurationEventDisposable?: vscode.Disposable; |
| 26 | + private validFileTypes = ["swift", "c", "cpp", "h", "hpp", "m", "mm"]; |
| 27 | + private disposables: vscode.Disposable[] = []; |
26 | 28 |
|
27 |
| - constructor(private folderContext: FolderContext) {} |
28 |
| - |
29 |
| - /** |
30 |
| - * Start onDidSave handler which will kick off compilation tasks |
31 |
| - * |
32 |
| - * The task works out which folder the saved file is in and then |
33 |
| - * will call `runTask` on the background compilation attached to |
34 |
| - * that folder. |
35 |
| - * */ |
36 |
| - static start(workspaceContext: WorkspaceContext): vscode.Disposable { |
37 |
| - const onDidSaveDocument = vscode.workspace.onDidSaveTextDocument(event => { |
38 |
| - if (configuration.backgroundCompilation === false) { |
39 |
| - return; |
40 |
| - } |
41 |
| - |
42 |
| - // is document a valid type for rebuild |
43 |
| - const languages = ["swift", "c", "cpp", "objective-c", "objective-cpp"]; |
44 |
| - let foundLanguage = false; |
45 |
| - languages.forEach(lang => { |
46 |
| - if (event.languageId === lang) { |
47 |
| - foundLanguage = true; |
| 29 | + constructor(private folderContext: FolderContext) { |
| 30 | + // We only want to configure the file watcher if background compilation is enabled. |
| 31 | + this.configurationEventDisposable = vscode.workspace.onDidChangeConfiguration(event => { |
| 32 | + if (event.affectsConfiguration("swift.backgroundCompilation", folderContext.folder)) { |
| 33 | + if (configuration.backgroundCompilation) { |
| 34 | + this.setupFileWatching(); |
| 35 | + } else { |
| 36 | + this.stopFileWatching(); |
48 | 37 | }
|
49 |
| - }); |
50 |
| - if (foundLanguage === false) { |
51 |
| - return; |
52 | 38 | }
|
| 39 | + }); |
| 40 | + |
| 41 | + if (configuration.backgroundCompilation) { |
| 42 | + this.setupFileWatching(); |
| 43 | + } |
| 44 | + } |
53 | 45 |
|
54 |
| - // is editor document in any of the current FolderContexts |
55 |
| - const folderContext = workspaceContext.folders.find(context => { |
56 |
| - return isPathInsidePath(event.uri.fsPath, context.folder.fsPath); |
57 |
| - }); |
| 46 | + private setupFileWatching() { |
| 47 | + const fileTypes = this.validFileTypes.join(","); |
| 48 | + const rootFolders = ["Sources", "Tests", "Snippets", "Plugins"].join(","); |
| 49 | + this.disposables.push( |
| 50 | + (this.workspaceFileWatcher = vscode.workspace.createFileSystemWatcher( |
| 51 | + `**/{${rootFolders}}/**/*.{${fileTypes}}` |
| 52 | + )) |
| 53 | + ); |
58 | 54 |
|
59 |
| - if (!folderContext) { |
60 |
| - return; |
61 |
| - } |
| 55 | + // Throttle events since many change events can be recieved in a short time if the user |
| 56 | + // does a "Save All" or a process writes several files in quick succession. |
| 57 | + this.disposables.push( |
| 58 | + this.workspaceFileWatcher.onDidChange( |
| 59 | + debounce( |
| 60 | + () => { |
| 61 | + this.runTask(); |
| 62 | + }, |
| 63 | + 100 /* 10 times per second */, |
| 64 | + { trailing: true } |
| 65 | + ) |
| 66 | + ) |
| 67 | + ); |
| 68 | + } |
62 | 69 |
|
63 |
| - // don't run auto-build if saving Package.swift as it clashes with the resolve |
64 |
| - // that is run after the Package.swift is saved |
65 |
| - if (path.join(folderContext.folder.fsPath, "Package.swift") === event.uri.fsPath) { |
66 |
| - return; |
67 |
| - } |
| 70 | + private stopFileWatching() { |
| 71 | + this.disposables.forEach(disposable => disposable.dispose()); |
| 72 | + } |
68 | 73 |
|
69 |
| - // run background compilation task |
70 |
| - folderContext.backgroundCompilation.runTask(); |
71 |
| - }); |
72 |
| - return { dispose: () => onDidSaveDocument.dispose() }; |
| 74 | + dispose() { |
| 75 | + this.configurationEventDisposable?.dispose(); |
| 76 | + this.disposables.forEach(disposable => disposable.dispose()); |
73 | 77 | }
|
74 | 78 |
|
75 | 79 | /**
|
|
0 commit comments