Skip to content

Commit 6af5db9

Browse files
committed
fix for same groupId:ArtifactId, sort by explorer/alpha
1 parent 174fa34 commit 6af5db9

5 files changed

Lines changed: 130 additions & 36 deletions

File tree

package.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,9 +157,39 @@
157157
"category": "Liberty",
158158
"title": "%commands.title.open.build.file%",
159159
"icon": "$(go-to-file)"
160+
},
161+
{
162+
"command": "liberty.explorer.sort.workspace",
163+
"category": "Liberty",
164+
"title": "Sort: Workspace"
165+
},
166+
{
167+
"command": "liberty.explorer.sort.workspace.active",
168+
"category": "Liberty",
169+
"title": "✓ Sort: Workspace"
170+
},
171+
{
172+
"command": "liberty.explorer.sort.alphabetical",
173+
"category": "Liberty",
174+
"title": "Sort: Alphabetical"
175+
},
176+
{
177+
"command": "liberty.explorer.sort.alphabetical.active",
178+
"category": "Liberty",
179+
"title": "✓ Sort: Alphabetical"
160180
}
161181
],
162182
"menus": {
183+
"commandPalette": [
184+
{
185+
"command": "liberty.explorer.sort.workspace.active",
186+
"when": "false"
187+
},
188+
{
189+
"command": "liberty.explorer.sort.alphabetical.active",
190+
"when": "false"
191+
}
192+
],
163193
"explorer/context": [
164194
{
165195
"command": "liberty.dev.add.project",
@@ -192,6 +222,26 @@
192222
"command": "liberty.dev.remove.project",
193223
"when": "view == liberty-dev",
194224
"group": "navigation@4"
225+
},
226+
{
227+
"command": "liberty.explorer.sort.workspace",
228+
"when": "view == liberty-dev && (liberty:sortOrder != workspace || !liberty:sortOrder)",
229+
"group": "2_sort@1"
230+
},
231+
{
232+
"command": "liberty.explorer.sort.workspace.active",
233+
"when": "view == liberty-dev && liberty:sortOrder == workspace",
234+
"group": "2_sort@1"
235+
},
236+
{
237+
"command": "liberty.explorer.sort.alphabetical",
238+
"when": "view == liberty-dev && liberty:sortOrder != alphabetical",
239+
"group": "2_sort@2"
240+
},
241+
{
242+
"command": "liberty.explorer.sort.alphabetical.active",
243+
"when": "view == liberty-dev && liberty:sortOrder == alphabetical",
244+
"group": "2_sort@2"
195245
}
196246
],
197247
"view/item/context": [

src/definitions/constants.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ export const CMD_OPEN_SUREFIRE_REPORT = "liberty.dev.open.surefire.report";
6969
export const CMD_OPEN_GRADLE_TEST_REPORT = "liberty.dev.open.gradle.test.report";
7070
export const CMD_ADD_PROJECT = "liberty.dev.add.project";
7171
export const CMD_REMOVE_PROJECT = "liberty.dev.remove.project";
72+
export const CMD_SORT_WORKSPACE = "liberty.explorer.sort.workspace";
73+
export const CMD_SORT_WORKSPACE_ACTIVE = "liberty.explorer.sort.workspace.active";
74+
export const CMD_SORT_ALPHABETICAL = "liberty.explorer.sort.alphabetical";
75+
export const CMD_SORT_ALPHABETICAL_ACTIVE = "liberty.explorer.sort.alphabetical.active";
76+
export const SORT_ORDER_KEY = "liberty.sortOrder";
77+
export type SortOrder = "workspace" | "alphabetical";
7278

7379
// ---------------------------------------------------------------------------
7480
// Project Discovery

src/extension.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
CMD_START, CMD_DEBUG, CMD_STOP, CMD_CUSTOM, CMD_START_CONTAINER,
2222
CMD_RUN_TESTS, CMD_OPEN_FAILSAFE_REPORT, CMD_OPEN_SUREFIRE_REPORT,
2323
CMD_OPEN_GRADLE_TEST_REPORT, CMD_ADD_PROJECT, CMD_REMOVE_PROJECT,
24+
CMD_SORT_WORKSPACE, CMD_SORT_WORKSPACE_ACTIVE, CMD_SORT_ALPHABETICAL, CMD_SORT_ALPHABETICAL_ACTIVE,
2425
} from "./definitions/constants";
2526
import path = require('path');
2627
import * as fs from "fs";
@@ -161,6 +162,10 @@ function registerCommands(context: ExtensionContext) {
161162
[CMD_OPEN_GRADLE_TEST_REPORT, (p?: LibertyProject) => devCommands.openReport("gradle", p)],
162163
[CMD_ADD_PROJECT, (uri: vscode.Uri) => devCommands.addProject(uri)],
163164
[CMD_REMOVE_PROJECT, () => devCommands.removeProject()],
165+
[CMD_SORT_WORKSPACE, () => projectProvider.setSortOrder("workspace")],
166+
[CMD_SORT_WORKSPACE_ACTIVE, () => projectProvider.setSortOrder("workspace")],
167+
[CMD_SORT_ALPHABETICAL, () => projectProvider.setSortOrder("alphabetical")],
168+
[CMD_SORT_ALPHABETICAL_ACTIVE, () => projectProvider.setSortOrder("alphabetical")],
164169
];
165170
context.subscriptions.push(
166171
...commandTable.map(([id, handler]) => vscode.commands.registerCommand(id, handler)),

src/liberty/projectDiscovery.ts

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,26 @@ async function stampProjects(
324324
return { projectsMap, mavenMetadataMap, gradleMetadataMap };
325325
}
326326

327+
/**
328+
* Sorts root projects to match the order of workspace folders in the Explorer view.
329+
* Projects not under any workspace folder are sorted last.
330+
*/
331+
export function sortByWorkspaceOrder(roots: LibertyProject[]): LibertyProject[] {
332+
const wsFolders = vscode.workspace.workspaceFolders ?? [];
333+
const folderIndex = (project: LibertyProject): number => {
334+
const idx = wsFolders.findIndex(f => {
335+
const folderPath = f.uri.fsPath.endsWith(vscodePath.sep) ? f.uri.fsPath : f.uri.fsPath + vscodePath.sep;
336+
return project.path.startsWith(folderPath);
337+
});
338+
return idx === -1 ? wsFolders.length : idx;
339+
};
340+
return [...roots].sort((a, b) => {
341+
const diff = folderIndex(a) - folderIndex(b);
342+
if (diff !== 0) { return diff; }
343+
return a.path.localeCompare(b.path);
344+
});
345+
}
346+
327347
/**
328348
* Wires parent-child relationships and computes rootProjects.
329349
*/
@@ -333,33 +353,6 @@ async function linkProjects(
333353
gradleMetadataMap: Map<string, gradleUtil.GradleProjectMetadata>
334354
): Promise<LibertyProject[]> {
335355
const t0 = Date.now();
336-
const mavenProjectsByArtifactId = new Map<string, LibertyProject>();
337-
const gradleProjectsByName = new Map<string, LibertyProject>();
338-
339-
for (const [path, metadata] of mavenMetadataMap.entries()) {
340-
const project = projectsMap.get(path);
341-
if (project) { mavenProjectsByArtifactId.set(metadata.artifactId, project); }
342-
}
343-
for (const [path, metadata] of gradleMetadataMap.entries()) {
344-
const project = projectsMap.get(path);
345-
if (project) { gradleProjectsByName.set(metadata.projectName, project); }
346-
}
347-
348-
for (const project of projectsMap.values()) {
349-
if (!project.parentArtifactId) { continue; }
350-
const parent = project.path.endsWith("pom.xml")
351-
? mavenProjectsByArtifactId.get(project.parentArtifactId)
352-
: gradleProjectsByName.get(project.parentArtifactId);
353-
console.log(`[link] ${project.artifactId} parentArtifactId=${project.parentArtifactId} -> parent found=${!!parent}`);
354-
if (parent && !parent.children.includes(project)) {
355-
project.parent = parent;
356-
parent.children.push(project);
357-
if (!project.isLibertyEnabled && parent.isLibertyEnabled) {
358-
project.isLibertyEnabled = true;
359-
console.debug(`${project.artifactId} inherits Liberty plugin from parent ${parent.artifactId}`);
360-
}
361-
}
362-
}
363356

364357
for (const [parentPath, parentMetadata] of mavenMetadataMap.entries()) {
365358
if (!parentMetadata.isAggregator || parentMetadata.modules.length === 0) { continue; }
@@ -382,6 +375,28 @@ async function linkProjects(
382375
}
383376
}
384377

378+
for (const [parentPath, parentMetadata] of gradleMetadataMap.entries()) {
379+
if (!parentMetadata.isAggregator || parentMetadata.subprojects.length === 0) { continue; }
380+
const parentProject = projectsMap.get(parentPath);
381+
if (!parentProject) { continue; }
382+
const parentDir = vscodePath.dirname(parentPath);
383+
for (const subproject of parentMetadata.subprojects) {
384+
const fsPath = subproject.replace(/:/g, "/").replace(/^\//, "");
385+
const childBuildPath = vscodePath.resolve(parentDir, fsPath, "build.gradle");
386+
const childProject = projectsMap.get(childBuildPath);
387+
if (childProject && !childProject.parent) {
388+
childProject.parent = parentProject;
389+
if (!parentProject.children.includes(childProject)) {
390+
parentProject.children.push(childProject);
391+
}
392+
if (!childProject.isLibertyEnabled && parentProject.isLibertyEnabled) {
393+
childProject.isLibertyEnabled = true;
394+
}
395+
console.debug(`Linked gradle subproject ${subproject} to parent ${parentMetadata.projectName} via filesystem path`);
396+
}
397+
}
398+
}
399+
385400
// Stamp aggregator contextValue
386401
for (const project of projectsMap.values()) {
387402
if (project.isAggregator) {
@@ -398,9 +413,11 @@ async function linkProjects(
398413
return project.children.some(child => hasLibertyDescendants(child));
399414
};
400415

401-
const rootProjects = Array.from(projectsMap.values())
402-
.filter(p => !p.parent)
403-
.filter(p => p.isLibertyEnabled || hasLibertyDescendants(p));
416+
const rootProjects = sortByWorkspaceOrder(
417+
Array.from(projectsMap.values())
418+
.filter(p => !p.parent)
419+
.filter(p => p.isLibertyEnabled || hasLibertyDescendants(p))
420+
);
404421
console.log(`[perf] linkProjects: ${Date.now() - t0}ms (${rootProjects.length} roots)`);
405422
return rootProjects;
406423
}

src/liberty/projectTreeProvider.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ import * as vscode from "vscode";
77
import * as util from "../util/helperUtil";
88
import { localize } from "../util/i18nUtil";
99
import { devModeRequirement } from "../util/helperUtil";
10-
import { UNTITLED_WORKSPACE } from "../definitions/constants";
10+
import { UNTITLED_WORKSPACE, SORT_ORDER_KEY, SortOrder } from "../definitions/constants";
1111
import { LibertyProject } from "./libertyProject";
1212
import { ProjectRegistry } from "./projectRegistry";
13-
import { discoverWorkspace } from "./projectDiscovery";
13+
import { discoverWorkspace, sortByWorkspaceOrder } from "./projectDiscovery";
1414

1515
// URI scheme used to signal dev-mode state to the FileDecorationProvider (enables green UI)
1616
// Format: liberty-dev://running/<encoded-project-path>
@@ -44,8 +44,6 @@ export class ProjectTreeProvider implements vscode.TreeDataProvider<LibertyProje
4444

4545
private _refreshing = false;
4646

47-
48-
4947
private _registry: ProjectRegistry;
5048

5149
public readonly decorationProvider = new LibertyDevDecorationProvider();
@@ -54,9 +52,20 @@ export class ProjectTreeProvider implements vscode.TreeDataProvider<LibertyProje
5452
this._registry = registry;
5553
this._onDidChangeTreeData = new vscode.EventEmitter<LibertyProject | undefined>();
5654
this.onDidChangeTreeData = this._onDidChangeTreeData.event;
55+
vscode.commands.executeCommand('setContext', 'liberty:sortOrder', this.getSortOrder());
5756
this.refresh();
5857
}
5958

59+
public getSortOrder(): SortOrder {
60+
return (this._registry.getContext().workspaceState.get<SortOrder>(SORT_ORDER_KEY)) ?? "workspace";
61+
}
62+
63+
public async setSortOrder(order: SortOrder): Promise<void> {
64+
await this._registry.getContext().workspaceState.update(SORT_ORDER_KEY, order);
65+
vscode.commands.executeCommand('setContext', 'liberty:sortOrder', order);
66+
await this.refresh();
67+
}
68+
6069
public static getInstance(): ProjectTreeProvider {
6170
return ProjectTreeProvider.instance;
6271
}
@@ -155,6 +164,13 @@ export class ProjectTreeProvider implements vscode.TreeDataProvider<LibertyProje
155164
return element;
156165
}
157166

167+
private sortRoots(roots: LibertyProject[]): LibertyProject[] {
168+
if (this.getSortOrder() === "alphabetical") {
169+
return [...roots].sort((a, b) => a.label.localeCompare(b.label));
170+
}
171+
return sortByWorkspaceOrder(roots);
172+
}
173+
158174
// eslint-disable-next-line @typescript-eslint/no-unused-vars
159175
public async getChildren(element?: LibertyProject): Promise<LibertyProject[]> {
160176
if (vscode.workspace.workspaceFolders === undefined) {
@@ -276,13 +292,13 @@ export class ProjectTreeProvider implements vscode.TreeDataProvider<LibertyProje
276292
(partial, foldersComplete, totalFolders) => {
277293
// Progressive tree update after each folder
278294
this._registry.setProjects(new Map(partial));
279-
this._registry.setRootProjects(Array.from(partial.values()).filter(p => !p.parent));
295+
this._registry.setRootProjects(this.sortRoots(Array.from(partial.values()).filter(p => !p.parent)));
280296
this._onDidChangeTreeData.fire(undefined);
281297
}
282298
);
283299

284300
this._registry.setProjects(projects);
285-
this._registry.setRootProjects(rootProjects);
301+
this._registry.setRootProjects(this.sortRoots(rootProjects));
286302
console.log(`[perf] updateProjects total: ${Date.now() - t0}ms (${projects.size} projects, ${rootProjects.length} roots)`);
287303
}
288304
}

0 commit comments

Comments
 (0)