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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only
import * as vscode from 'vscode';
import * as cmakeApi from 'vscode-cmake-tools';
import { WorkspaceStateManager } from '@/state';
import { coreAPI, kitManager } from '@/extension';
import { createLogger, QtWorkspaceConfigMessage } from 'qt-lib';
import { Project, ProjectManager } from 'qt-lib';
import {
getQtInsRoot,
getQtPathsExe,
getSelectedKit
} from '@cmd/register-qt-path';
import { analyzeKit } from '@/kit-manager';
const logger = createLogger('project');
export async function createCppProject(
folder: vscode.WorkspaceFolder,
context: vscode.ExtensionContext
) {
logger.info('Creating project:"' + folder.uri.fsPath + '"');
const api = await cmakeApi.getCMakeToolsApi(cmakeApi.Version.latest);
let cmakeProject: cmakeApi.Project | undefined;
if (api) {
cmakeProject = await api.getProject(folder.uri);
}
const buildDir = await cmakeProject?.getBuildDirectory();
return Promise.resolve(
new CppProject(folder, context, cmakeProject, buildDir)
);
}
// Project class represents a workspace folder in the extension.
export class CppProject implements Project {
private readonly _disposables: vscode.Disposable[] = [];
private readonly _stateManager: WorkspaceStateManager;
private readonly _cmakeProject: cmakeApi.Project | undefined;
private _buildDir: string | undefined;
constructor(
private readonly _folder: vscode.WorkspaceFolder,
readonly _context: vscode.ExtensionContext,
cmakeProject: cmakeApi.Project | undefined,
buildDir: string | undefined
) {
this._cmakeProject = cmakeProject;
this._stateManager = new WorkspaceStateManager(_context, _folder);
this._buildDir = buildDir;
if (this._cmakeProject) {
const onSelectedConfigurationChangedHandler =
this._cmakeProject.onSelectedConfigurationChanged(
async (configurationType: cmakeApi.ConfigurationType) => {
if (configurationType === cmakeApi.ConfigurationType.Kit) {
const kit = await getSelectedKit(this.folder);
if (kit) {
analyzeKit(kit);
}
const selectedKitPath = kit ? getQtInsRoot(kit) : undefined;
const message = new QtWorkspaceConfigMessage(this.folder);
message.config.set('selectedKitPath', selectedKitPath);
const selectedQtPaths = kit ? getQtPathsExe(kit) : undefined;
message.config.set('selectedQtPaths', selectedQtPaths);
coreAPI?.update(message);
}
}
);
const onCodeModelChangedHandler = this._cmakeProject.onCodeModelChanged(
async () => {
const prevbuildDir = this._buildDir;
const currentBuildDir = await this._cmakeProject?.getBuildDirectory();
if (prevbuildDir !== currentBuildDir) {
logger.info(
'Build directory changed:',
currentBuildDir ?? 'undefined'
);
this._buildDir = currentBuildDir;
const message = new QtWorkspaceConfigMessage(this.folder);
message.config.set('buildDir', currentBuildDir);
coreAPI?.update(message);
}
}
);
this._disposables.push(onCodeModelChangedHandler);
this._disposables.push(onSelectedConfigurationChangedHandler);
}
}
public getStateManager() {
return this._stateManager;
}
get folder() {
return this._folder;
}
get buildDir() {
return this._buildDir;
}
dispose() {
logger.info('Disposing project:', this._folder.uri.fsPath);
for (const d of this._disposables) {
d.dispose();
}
}
}
export class CppProjectManager extends ProjectManager<CppProject> {
constructor(override readonly context: vscode.ExtensionContext) {
super(context, createCppProject);
this._disposables.push(
this.onProjectAdded((project: CppProject) => {
logger.info('Adding project:', project.folder.uri.fsPath);
kitManager.addProject(project);
})
);
this._disposables.push(
this.onProjectRemoved((project: CppProject) => {
kitManager.removeProject(project);
})
);
}
}
|