Skip to content

Commit 8e03dca

Browse files
committed
refactor project root folder for multi root
1 parent fbeb0a8 commit 8e03dca

File tree

2 files changed

+62
-16
lines changed

2 files changed

+62
-16
lines changed

src/extension.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { join } from 'path';
44
import { format } from 'util';
55
import {
66
ExtensionContext,
7+
RelativePattern,
78
TextDocument,
89
commands,
910
extensions,
@@ -139,6 +140,15 @@ export async function activate(
139140

140141
registerBuildifierFormatter();
141142

143+
// if this is a multi-root project, create a listener to refresh the symlinked project root directory on file add/remove
144+
if (ProjectViewManager.isMultiRoot()) {
145+
const w = workspace.createFileSystemWatcher(
146+
new RelativePattern(workspaceRoot, '*')
147+
);
148+
w.onDidCreate((_e) => ProjectViewManager.syncWorkspaceRoot());
149+
w.onDidDelete((_e) => ProjectViewManager.syncWorkspaceRoot());
150+
}
151+
142152
// trigger a refresh of the tree view when any task get executed
143153
tasks.onDidStartTask((_) => BazelRunTargetProvider.instance.refresh());
144154
tasks.onDidEndTask((_) => BazelRunTargetProvider.instance.refresh());

src/projectViewManager.ts

Lines changed: 52 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
import { writeFileSync } from 'fs';
1+
import {
2+
existsSync,
3+
mkdirSync,
4+
readdirSync,
5+
rmSync,
6+
statSync,
7+
symlinkSync,
8+
writeFileSync,
9+
} from 'fs';
10+
import { homedir } from 'os';
11+
import { sep } from 'path';
212
import {
313
commands,
414
ConfigurationTarget,
@@ -15,8 +25,9 @@ import { getVscodeConfig, getWorkspaceRoot } from './util';
1525
export namespace ProjectViewManager {
1626
const workspaceRoot = getWorkspaceRoot();
1727
const workspaceRootName = workspaceRoot.split('/').reverse()[0];
28+
const projectRootSymlinks = `${homedir}${sep}${workspaceRootName}`;
1829

19-
function isMultiRoot(): boolean {
30+
export function isMultiRoot(): boolean {
2031
return !!workspace.workspaceFile;
2132
}
2233

@@ -42,7 +53,7 @@ export namespace ProjectViewManager {
4253
};
4354
writeFileSync(
4455
`${workspaceRoot}/workspace.code-workspace`,
45-
Buffer.from(JSON.stringify(workspaceFile, null, 2))
56+
JSON.stringify(workspaceFile, null, 2)
4657
);
4758

4859
// cleanup all old single root workspace files
@@ -83,7 +94,8 @@ export namespace ProjectViewManager {
8394
async function getDisplayFolders(): Promise<string[]> {
8495
let displayFolders = new Set<string>(['.eclipse']); // TODO bubble this out to a setting
8596
if (isMultiRoot()) {
86-
displayFolders.add('.');
97+
syncWorkspaceRoot();
98+
displayFolders.add(projectRootSymlinks);
8799
}
88100
try {
89101
const bazelProjectFile = await getBazelProjectFile();
@@ -141,18 +153,17 @@ export namespace ProjectViewManager {
141153
0,
142154
workspace.workspaceFolders?.length,
143155
...displayFolders.map((f) => {
144-
const moduleUri = Uri.file(`${workspaceRoot}/${f}`);
145-
let moduleName = f;
146-
if (moduleName === '.') {
147-
moduleName = workspaceRootName;
148-
}
149-
if (f.includes('/')) {
150-
moduleName = f.replaceAll('/', ' ⇾ ');
156+
if (f === projectRootSymlinks) {
157+
return {
158+
uri: Uri.file(projectRootSymlinks),
159+
name: workspaceRootName,
160+
};
161+
} else {
162+
return {
163+
uri: Uri.file(`${workspaceRoot}/${f}`),
164+
name: f.replaceAll(sep, ' ⇾ '),
165+
};
151166
}
152-
return {
153-
uri: moduleUri,
154-
name: moduleName,
155-
};
156167
})
157168
);
158169
return Promise.resolve(displayFolders);
@@ -176,7 +187,12 @@ export namespace ProjectViewManager {
176187

177188
const fileWatcherExcludePattern = viewAll
178189
? ''
179-
: `**/!(${Array.from(displayFolders.filter((s) => s !== '.').sort()).join('|')})/**`;
190+
: `**/!(${Array.from(
191+
displayFolders
192+
.filter((e) => e !== '')
193+
.filter((s) => s !== '.')
194+
.sort()
195+
).join('|')})/**`;
180196

181197
if (viewAll) {
182198
// if viewAll and existing config doesn't contain .eclipse return
@@ -242,4 +258,24 @@ export namespace ProjectViewManager {
242258
function rootDirOnly(dirs: string[]): string[] {
243259
return dirs.map((d) => d.split('/')[0]);
244260
}
261+
262+
export function syncWorkspaceRoot() {
263+
if (existsSync(projectRootSymlinks)) {
264+
rmSync(projectRootSymlinks, { recursive: true }); // delete
265+
}
266+
267+
mkdirSync(projectRootSymlinks);
268+
269+
readdirSync(workspaceRoot).forEach((f) => {
270+
const fpath = `${workspaceRoot}${sep}${f}`;
271+
if (existsSync(fpath)) {
272+
const stats = statSync(fpath);
273+
if (stats.isFile()) {
274+
symlinkSync(fpath, `${projectRootSymlinks}${sep}${f}`);
275+
}
276+
}
277+
});
278+
279+
commands.executeCommand('workbench.files.action.refreshFilesExplorer');
280+
}
245281
}

0 commit comments

Comments
 (0)