Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable storage of meson.build in a non-root directory in the workspace #179

Merged
merged 12 commits into from
Nov 14, 2023
Merged

Conversation

wolfpld
Copy link
Contributor

@wolfpld wolfpld commented Nov 3, 2023

This PR allows the meson.build file to be placed in a subdirectory within the workspace.

The current behavior of the extension is inconsequential, as some checks already look for meson.build in the entire workspace, and the activation event fires when you manually open meson.build that is stored in a subdirectory, resulting in a prompt to configure the workspace. Of course, there's no support for such behavior within the extension, so things fail.

This is similar to #22, but works automatically. No user-facing configuration option is exposed. If multiple meson.build files are found in the workspace, the 'first' one is used. I plan to extend this to allow the user to switch between different meson.build configurations within the same workspace, but this PR is a prerequisite for those future changes.

This PR also fixes a regression introduced in 60dc5f7. This commit removed the "configure on open" condition, rendering the reconfigure prompt completely useless and severely degrading the new user experience. The PR restores the removed condition.

In an effort to make things more robust, multiple recalculations of the build directory in different parts of the code have been replaced by a single calculation on extension activation, which is then stored as a workspace-relative memento that can be referenced when needed.

To make things consistent, the working directory provided by debug configurations and when running tests is now set to the "source directory" in the meson setup understanding, i.e. the directory where the meson.build file resides.

There are two places in the code where vscode.workspace.rootPath is still used instead of the source directory. I can't check if this is valid or not.

  1. Attempting to explore the targets in the Meson section of the activity bar fails with a s.sources is not iterable (cannot read property undefined) error message. This also happens in the currently deployed extension.

  2. The useCompileCommands function provides data for Microsoft's C++ extension, which I am not interested in. The alternative clangd extension can use the same functionality with the compile_commands.json file, and properly providing it for clangd would also show how to do it for Microsoft's extension. But there's another can of worms to tackle to even try to do anything with it (https://mastodon.gamedev.place/@wolfpld/111346306341679920).

@tristan957
Copy link
Contributor

I plan to look at this for 1.17. Thanks!

…pace.

This fixes logic mismatch between the activation events and the check for
existence of project inside the workspace. When meson file is outside
the root directory, the extension will still activate when the you open
the file.

The extension is still not able to handle non-root meson file, but at
least now the failure mode is promptly exposed, instead of being hidden.
@wolfpld
Copy link
Contributor Author

wolfpld commented Nov 13, 2023

If multiple meson.build files are found in the workspace, the 'first' one is used.

The 'first' here is not well defined, as suspected. It seems that the file search is asynchronous, as I have seen the meson.build being randomly selected when entering the workspace. This is a regression that needs to be fixed by implementing a proper selection solution within this PR, not at a later stage. The problem may occur even if there's only one meson.build in the repository, for example if a third-party submodule also provides its own meson.build.

Another problem is the meson subdir command, which includes meson.build files from subdirectories. The solution here is to remove any meson.build files from the selection list that have other meson.build files referencing them.

@wolfpld
Copy link
Contributor Author

wolfpld commented Nov 14, 2023

I have added a selection dialog when there is more than one meson.build file in the workspace. It appears when the user chooses to do the initial configuration from the popup. The user's selection is saved persistently for the current workspace.

obraz

If the selection matches the (randomly chosen) first item in the array of found meson.build files, the reconfiguration command is issued as before, since everything is already set up as it should be.

Otherwise, a flag is set that will survive a window reload, and the reload command is issued immediately. When the extension initialization process starts after this reload, the previously selected meson.build is used instead of the first found file. The flag allows to bypass the configuration prompt and the meson.build selector.

While the meson.build selection is saved for the workspace, the code logic should handle cases where this file is moved to another directory by doing the selection process again.

Filtering the subdir commands is not yet handled.

Currently there's no way to switch to a different meson.build file after the initial selection, other than removing the build subdirectory. I would like to add this as a command and to the Meson sidebar.

@tristan957
Copy link
Contributor

Do you plan on adding the rest of the features in this PR?

@wolfpld
Copy link
Contributor Author

wolfpld commented Nov 14, 2023

Yes.

src/extension.ts Outdated
@@ -207,6 +207,10 @@ export async function activate(ctx: vscode.ExtensionContext) {
break;
}
}

if (configureOnOpen === true) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you remove the comparison?

@@ -21,6 +21,7 @@ import { SettingsKey, TaskQuickPickItem } from "./types";
import { createLanguageServerClient } from "./lsp/common";

export let extensionPath: string;
export let workspaceState: vscode.Memento;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain a little more what this commit is doing, like what is a memento?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Memento is part of the VS Code API. I would expect the developer to be familiar with it.

https://code.visualstudio.com/api/references/vscode-api#Memento

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know the API and am not the original author. I just maintain it with bare minimum knowledge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that was not meant as a dig at you, but as a general way of saying that a developer working on this code would know the API provided by VS Code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will add a reference to https://www.chrishasz.com/blog/2020/07/28/vscode-how-to-use-local-storage-api/ to the commit message, which explains what it does a bit better than the lackluster VS Code documentation.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We definitely need more contributors to this extension. You seem to have a solid handle on this.

@@ -37,6 +39,8 @@ export async function activate(ctx: vscode.ExtensionContext) {
const root = vscode.workspace.workspaceFolders[0].uri.fsPath;
const buildDir = workspaceRelative(extensionConfiguration("buildFolder"));

workspaceState.update("mesonbuild.buildDir", buildDir);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call it mesonbuild.buildFolder? Rename the variable too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I do not like the Microsoft newspeak that replaces directory with folder. The buildDir name is pervasive in the repository.

[18:34 wolf@oberon:~/vscode-meson]% git grep buildDir | wc -l
78
[18:34 wolf@oberon:~/vscode-meson]% git grep buildFolder | wc -l
7

For example, the current main branch:

const buildDir = workspaceRelative(extensionConfiguration("buildFolder"));

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Let's work on replacing the setting in the future. No big deal

@@ -45,7 +45,9 @@ export async function activate(ctx: vscode.ExtensionContext) {
const mesonFile = mesonFiles[0];
const sourceDir = dirname(mesonFile.fsPath);
const buildDir = relativeBuildDir(mesonFile.fsPath);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add this newline in the original commit?

src/utils.ts Outdated
@@ -79,7 +79,10 @@ export async function getTargetName(target: Target) {
const layout = await _layoutPromise;

if (layout === "mirror") {
let relativePath = path.relative(vscode.workspace.rootPath!, path.dirname(target.defined_in));
let relativePath = path.relative(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you make this const?

@@ -127,7 +128,7 @@ export async function testDebugHandler(
name: `meson-debug-${test.name}`,
type: debugType,
request: "launch",
cwd: test.workdir || buildDir,
cwd: test.workdir || sourceDir,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make things consistent, the working directory provided by debug configurations and when running tests is now set to the "source directory" in the meson setup understanding, i.e. the directory where the meson.build file resides.

It makes little sense to me to have different behavior when you run the tests and when you run the program through debug providers. If having the specific working directory for tests is important to the user, there's the test.workdir for that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would make sense to me, but other people may run the tests from the builddir. I don't know. I am fine accepting the patch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, I don't have a strong preference for how this should work, but it seems better to make it consistent across the board.

src/extension.ts Outdated
Comment on lines 237 to 251
if (selection) {
if (mesonFiles[selection.index] !== mesonFile) {
vscode.commands.executeCommand("workbench.action.reloadWindow");
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we just move this into the try block? Also, let's just combine the two boolean checks into 1.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I was mirroring this section:

let taskItem;
try {
taskItem = await pickTask(mode);
} catch (err) {
// Pick cancelled.
}
if (taskItem != null) {
runTask(taskItem.task);
}

I'm not sure if the showQuickPick method is even able to throw. The documentation states that it returns "a promise that resolves to the selected items or undefined" and does not mention any error handling.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the comment is wrong. The following does not work:

obraz

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have removed the try/catch section and added code do prevent reconfigure running if selection was cancelled.

@wolfpld
Copy link
Contributor Author

wolfpld commented Nov 14, 2023

All of your notes should now be addressed.

@tristan957
Copy link
Contributor

Looks like the build step failed. Can you see about fixing it?

@wolfpld
Copy link
Contributor Author

wolfpld commented Nov 14, 2023

The failure seems to be a fluke in the CI/CD system, not something related to the code itself. I don't think I have any way to rerun the test.

@wolfpld
Copy link
Contributor Author

wolfpld commented Nov 14, 2023

I force pushed the last commit with an updated date to rerun the checks. Now they all pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants