Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1914,12 +1914,12 @@
"group": "1_javaactions"
},
{
"when": "explorerResourceIsFolder&&javaLSReady",
"when": "explorerResourceIsFolder&&javaLSReady&&resourcePath in java.projects",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

java.projects only holds project root paths, and in is an exact-membership check (no prefix/descendant matching). So this only matches when you right-click the project root itself.

But Add/Remove Source Path are mostly used on subfolders (e.g. marking src/test as a source root) — those will now stop showing the action entirely, which is the opposite of what we want. Same applies to the removeFromSourcePath when just below.

For remove, what you probably want is a separate java.sourceFolders context (the actual source paths) and gate on resourcePath in java.sourceFolders. Add is trickier, since "folder is inside a project" can't really be expressed with exact membership.

"command": "java.project.addToSourcePath.command",
"group": "1_javaactions@1"
},
{
"when": "explorerResourceIsFolder&&javaLSReady",
"when": "explorerResourceIsFolder&&javaLSReady&&resourcePath in java.projects",
"command": "java.project.removeFromSourcePath.command",
"group": "1_javaactions@2"
}
Expand Down
9 changes: 8 additions & 1 deletion src/standardLanguageClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export class StandardLanguageClient {

public registerLanguageClientActions(context: ExtensionContext, hasImported: boolean, jdtEventEmitter: EventEmitter<Uri>) {
activationProgressNotification.showProgress();
this.languageClient.onNotification(StatusNotification.type, (report) => {
this.languageClient.onNotification(StatusNotification.type, async (report) => {
// Resolve serverRunning on the first status notification from the server,
// indicating the server process is alive and can accept requests.
apiManager.resolveServerRunningPromise();
Expand Down Expand Up @@ -152,6 +152,13 @@ export class StandardLanguageClient {
// Disable the client-side snippet provider since LS is ready.
snippetCompletionProvider.dispose();
registerDocumentValidationListener(context, this.languageClient);
try {
const projectUris = await getAllJavaProjects();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

awaiting this means javaLSReady (set a few lines down) now waits on a full LS round-trip — and gets blocked completely if this call ever hangs. Since javaLSReady gates a lot of menus/keybindings, I'd set it first and then populate java.projects fire-and-forget (it already has its own try/catch).

const projectPaths = projectUris.map((uriString) => Uri.parse(uriString).fsPath.replace(/[\\/]$/, ''));
await commands.executeCommand('setContext', 'java.projects', projectPaths);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is only set once, on ServiceReady. Projects change over time (import/delete, classpath updates) and this never refreshes — so newly imported projects won't get the action, and deleted ones keep it until a reload.

Worth extracting a small helper and also calling it from onDidProjectsImport / onDidProjectsDelete (both already used in runtimeStatusBarProvider.ts).

} catch (error) {
logger.error(error);
}
commands.executeCommand('setContext', 'javaLSReady', true);
break;
case 'Started':
Expand Down
Loading