Skip to content

Commit a0e78c1

Browse files
ar1m4nDimitar UshatovhanniavaleraCopilot
authored
Implement outlineViewType setting that changes the Project Outline View (#3799) (#4538)
* Implement outlineViewType setting that changes the Project Outline View (#3799) * fixing lint errors * Fix outlineViewType setting to properly toggle between tree and list views - Move onChange subscription from workspace-level to per-project ConfigurationReader, fixing resource-scoped setting detection and multi-project refresh (Bugs #1 and #2 from audit) - Branch in WorkspaceFolderNode.updateCodeModel() to restore the pre-1.15 multi-project outline in tree mode, bypassing the populateViewCodeModel() flattening (Bug #3) - Revert ProjectNode to original 3-param constructor (remove ConfigurationReader dependency) - Revert ProjectNode.update() to standard folder-based target grouping (tree structure comes from separate ProjectNodes) - Add CHANGELOG entry Co-authored-by: Copilot <[email protected]> --------- Co-authored-by: Dimitar Ushatov <[email protected]> Co-authored-by: Hannia Valera <[email protected]> Co-authored-by: Copilot <[email protected]>
1 parent 7138e9e commit a0e78c1

8 files changed

Lines changed: 46 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Features:
2020
- Complete Bookmarks context menu with "Set Build Target", "Set Launch/Debug Target", "Open CMakeLists.txt", and "Run Utility Target" actions to match the Project Outline. [#4788](https://github.com/microsoft/vscode-cmake-tools/issues/4788)
2121
- Relax `intelliSenseMode` validation in CMake Presets. [#4815](https://github.com/microsoft/vscode-cmake-tools/issues/4815) [@halflifefan](https://github.com/halflifefan)
2222
- Support string arrays in kit `cmakeSettings` to pass CMake lists without escaping semicolons (e.g., `"LLVM_ENABLE_PROJECTS": ["clang", "lld"]`). [#4503](https://github.com/microsoft/vscode-cmake-tools/issues/4503)
23+
- Add `cmake.outlineViewType` setting to toggle the Project Outline between a flat list view and the prior hierarchical tree view that shows each CMake project separately. [#3799](https://github.com/microsoft/vscode-cmake-tools/issues/3799) [#4538](https://github.com/microsoft/vscode-cmake-tools/pull/4538) [@ar1m4n](https://github.com/ar1m4n)
2324

2425
Improvements:
2526
- Run tests sequentially in alphabetical order (matching the Test Explorer display order) when `cmake.ctest.allowParallelJobs` is disabled. [#4829](https://github.com/microsoft/vscode-cmake-tools/issues/4829)

docs/cmake-settings.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ Options that support substitution, in the table below, allow variable references
7777
| `cmake.options.advanced` | Advanced options for CMake Tools. | See package.json | no |
7878
| `cmake.options.statusBarVisibility` | Controls visibility of the status bar. | `hidden` | no |
7979
| `cmake.outputLogEncoding` | Encoding to use for tool output. | `auto` | no |
80+
| `cmake.outlineViewType` | Project Outline View`s type. | `["list", "tree"]` | no |
8081
| `cmake.parallelJobs` | Specify the number of jobs run in parallel during the build. Using the value `0` will detect and use the number of CPUs. Using the value `1` will disable build parallelism. | `0` | no |
8182
| `cmake.parseBuildDiagnostics` | If `true`, parse compiler output for diagnostics. | `true` | no |
8283
| `cmake.pinnedCommands` | List of commands pinned to the command palette. | `["workbench.action.tasks.configureTaskRunner", "workbench.action.tasks.runTask"]` | no |

package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3292,6 +3292,16 @@
32923292
],
32933293
"scope": "window"
32943294
},
3295+
"cmake.outlineViewType": {
3296+
"type": "string",
3297+
"enum": [
3298+
"list",
3299+
"tree"
3300+
],
3301+
"default": "list",
3302+
"description": "%cmake-tools.configuration.cmake.outlineViewType.description%",
3303+
"scope": "resource"
3304+
},
32953305
"cmake.options.advanced": {
32963306
"type": "object",
32973307
"default": {

package.nls.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@
428428
},
429429
"cmake-tools.configuration.cmake.launchBehavior.newTerminal.markdownDescriptions": "A new terminal instance is created and the target is launched in it. Existing terminals are not automatically cleaned up.",
430430
"cmake-tools.configuration.cmake.loadCompileCommands.description": "Controls whether the extension reads compile_commands.json to enable single file compilation.",
431+
"cmake-tools.configuration.cmake.outlineViewType.description": "Project Outline View`s type. Available options are: \"list\" and \"tree\".",
431432
"cmake-tools.command.cmake.projectStatus.update.title": "Refresh the project status",
432433
"cmake-tools.command.cmake.pinnedCommands.add.title": "Add a CMake command to pin",
433434
"cmake-tools.command.cmake.pinnedCommands.remove.title": "Unpin Command",

src/config.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ export interface ExtensionConfigurationSettings {
258258
additionalBuildProblemMatchers: BuildProblemMatcherConfig[];
259259
shell: string | null;
260260
modifyLists: ModifyListsSettings;
261+
outlineViewType: string;
261262
}
262263

263264
type EmittersOf<T> = {
@@ -679,6 +680,10 @@ export class ConfigurationReader implements vscode.Disposable {
679680
return this.configData.modifyLists;
680681
}
681682

683+
get outlineViewType(): string {
684+
return this.configData.outlineViewType;
685+
}
686+
682687
private readonly emitters: EmittersOf<ExtensionConfigurationSettings> = {
683688
autoSelectActiveFolder: new vscode.EventEmitter<boolean>(),
684689
defaultActiveFolder: new vscode.EventEmitter<string | null>(),
@@ -754,7 +759,8 @@ export class ConfigurationReader implements vscode.Disposable {
754759
additionalBuildProblemMatchers: new vscode.EventEmitter<BuildProblemMatcherConfig[]>(),
755760
shell: new vscode.EventEmitter<string | null>(),
756761
setBuildTargetSameAsLaunchTarget: new vscode.EventEmitter<boolean>(),
757-
modifyLists: new vscode.EventEmitter<ModifyListsSettings>()
762+
modifyLists: new vscode.EventEmitter<ModifyListsSettings>(),
763+
outlineViewType: new vscode.EventEmitter<string>()
758764
};
759765

760766
/**

src/extension.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export class ExtensionManager implements vscode.Disposable {
190190
subs.push(project.onTargetNameChanged(FireLate, () => this.updateCodeModel(project)));
191191
subs.push(project.onLaunchTargetNameChanged(FireLate, () => this.updateCodeModel(project)));
192192
subs.push(project.onActiveBuildPresetChanged(FireLate, () => this.updateCodeModel(project)));
193+
subs.push(project.workspaceContext.config.onChange('outlineViewType', () => this.updateCodeModel(project)));
193194
subs.push(project.cTestController.onTestsChanged(() => this.updateTestsInOutline(project)));
194195
this.codeModelUpdateSubs.set(project.folderPath, subs);
195196
rollbar.takePromise('Post-folder-open', { folder: folder, project: project }, this.postWorkspaceOpen(project));

src/ui/projectOutline/projectOutline.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -713,10 +713,6 @@ export class WorkspaceFolderNode extends BaseNode {
713713

714714
private readonly _projects = new Map<string, Map<string, ProjectNode>>();
715715

716-
private getNode(cmakeProject: CMakeProject, modelProjectName: string) {
717-
return this._projects.get(cmakeProject.folderPath)?.get(modelProjectName);
718-
}
719-
720716
private setNode(cmakeProject: CMakeProject, modelProjectName: string, node: ProjectNode) {
721717
let sub_map = this._projects.get(cmakeProject.folderPath);
722718
if (!sub_map) {
@@ -737,23 +733,37 @@ export class WorkspaceFolderNode extends BaseNode {
737733
return;
738734
}
739735

740-
if (model.configurations[0].projects.length === 0) {
736+
const configuration = model.configurations[0];
737+
if (configuration.projects.length === 0) {
741738
this.removeNodes(cmakeProject);
742739
ctx.nodesToUpdate.push(this);
743740
return;
744741
}
745742

746-
const projectOutlineModel = populateViewCodeModel(model);
747-
const rootProject = projectOutlineModel.project;
748-
let item = this.getNode(cmakeProject, rootProject.name);
749-
if (!item) {
750-
// Remove stale entries for this cmakeProject so that a renamed
751-
// project replaces the old node instead of appearing alongside it.
752-
this.removeNodes(cmakeProject);
753-
item = new ProjectNode(rootProject.name, this.wsFolder, cmakeProject.folderPath);
743+
const outlineViewType = cmakeProject.workspaceContext.config.outlineViewType;
744+
745+
// Always remove existing nodes first to ensure clean state when
746+
// switching between view types or when projects change.
747+
this.removeNodes(cmakeProject);
748+
749+
if (outlineViewType === "tree") {
750+
// Tree mode: create a separate ProjectNode for each CMake project,
751+
// restoring the pre-1.15 hierarchical outline.
752+
for (const project of configuration.projects) {
753+
const item = new ProjectNode(project.name, this.wsFolder, project.sourceDirectory);
754+
this.setNode(cmakeProject, project.name, item);
755+
item.update(project, ctx);
756+
}
757+
} else {
758+
// List mode (default): flatten all projects into a single node.
759+
const projectOutlineModel = populateViewCodeModel(model);
760+
const rootProject = projectOutlineModel.project;
761+
const item = new ProjectNode(rootProject.name, this.wsFolder, cmakeProject.folderPath);
754762
this.setNode(cmakeProject, rootProject.name, item);
763+
item.update(rootProject, ctx);
755764
}
756-
item.update(rootProject, ctx);
765+
766+
ctx.nodesToUpdate.push(this);
757767
}
758768

759769
getChildren() {

test/unit-tests/config.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ function createConfig(conf: Partial<ExtensionConfigurationSettings>): Configurat
9191
additionalBuildProblemMatchers: [],
9292
shell: null,
9393
setBuildTargetSameAsLaunchTarget: false,
94+
outlineViewType: "list",
9495
modifyLists: {
9596
addNewSourceFiles: 'ask',
9697
removeDeletedSourceFiles: 'ask',

0 commit comments

Comments
 (0)