aboutsummaryrefslogtreecommitdiffstats
path: root/qt-lib/src/project.ts
blob: 4a1c8fd85a60b1705f473548fb774dd92c11b0d2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only

import * as vscode from 'vscode';

export interface Project {
  folder: vscode.WorkspaceFolder;
  dispose(): void;
}

export class ProjectManager<ProjectType extends Project> {
  protected readonly _disposables: vscode.Disposable[] = [];
  projects = new Set<ProjectType>();
  private readonly _addEmitter = new vscode.EventEmitter<ProjectType>();
  private readonly _removeEmitter = new vscode.EventEmitter<ProjectType>();
  private _newProjectCallback: (
    folder: vscode.WorkspaceFolder,
    context: vscode.ExtensionContext
  ) => Promise<ProjectType | undefined>;

  constructor(
    readonly context: vscode.ExtensionContext,
    newProjectCallback: (
      folder: vscode.WorkspaceFolder,
      context: vscode.ExtensionContext
    ) => Promise<ProjectType | undefined>
  ) {
    this._newProjectCallback = newProjectCallback;
    this.watchProjects(context);
  }

  public addProject(project: ProjectType) {
    this.projects.add(project);
  }

  public removeProject(project: ProjectType) {
    this._removeEmitter.fire(project);
    this.projects.delete(project);
  }

  public set newProjectCallback(
    callback: (
      folder: vscode.WorkspaceFolder,
      context: vscode.ExtensionContext
    ) => Promise<ProjectType | undefined>
  ) {
    this._newProjectCallback = callback;
  }

  public get newProjectCallback() {
    return this._newProjectCallback;
  }

  public getProjects() {
    return this.projects;
  }

  public getProject(folder: vscode.WorkspaceFolder): ProjectType | undefined {
    return Array.from(this.projects).find(
      (project) => project.folder === folder
    );
  }

  public get onProjectAdded() {
    return this._addEmitter.event;
  }

  public get onProjectRemoved() {
    return this._removeEmitter.event;
  }

  protected watchProjects(context: vscode.ExtensionContext) {
    vscode.workspace.onDidChangeWorkspaceFolders(async (event) => {
      for (const folder of event.removed) {
        const project = this.getProject(folder);
        if (!project) {
          continue;
        }
        project.dispose();
        this.removeProject(project);
      }
      for (const folder of event.added) {
        const project = await this._newProjectCallback(folder, context);
        if (!project) {
          continue;
        }
        this.addProject(project);
        this._addEmitter.fire(project);
      }
    });
  }
  public findProjectContainingFile(uri: vscode.Uri) {
    return Array.from(this.projects).find((project) => {
      const ret = uri.toString().startsWith(project.folder.uri.toString());
      return ret;
    });
  }
  dispose() {
    for (const project of this.projects) {
      project.dispose();
    }
    this.projects.clear();
    for (const d of this._disposables) {
      d.dispose();
    }
  }
}