From f2d5a24f1a059f4ac00cbf35ae8dab08afbb106c Mon Sep 17 00:00:00 2001 From: Duy Bui Date: Fri, 29 May 2026 18:32:20 +0700 Subject: [PATCH 1/3] Create projects for new targets on re-importing --- .../com/bazel/jdt/BazelCommandHandler.java | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java index e81613a..c3d0f27 100644 --- a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java +++ b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java @@ -98,7 +98,14 @@ private Object handleImportProject(List arguments) { } String[] targets = bridge.discoverTargets(scopePatterns, bridge.getBuildFlags()); - BazelClasspathManager.refreshClasspath(); + + java.util.List newTargetLabels = createProjectsForNewTargets(workspacePath, targets, bridge); + + if (!newTargetLabels.isEmpty()) { + BazelClasspathManager.refreshClasspathForTargets(newTargetLabels); + } else { + BazelClasspathManager.refreshClasspath(); + } return null; } catch (Exception e) { LOG.log(new Status(IStatus.ERROR, "com.bazel.jdt", "Bazel import failed", e)); @@ -106,6 +113,71 @@ private Object handleImportProject(List arguments) { } } + private java.util.List createProjectsForNewTargets(String workspacePath, String[] targets, BazelBridge bridge) { + java.util.Set existingTargetLabels = getExistingTargetLabels(); + java.util.Set newTargets = findNewTargets(targets, existingTargetLabels); + + LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", + "Discovered " + newTargets.size() + " new targets (existing: " + existingTargetLabels.size() + ")")); + + if (!newTargets.isEmpty()) { + createProjectsForTargets(workspacePath, newTargets, bridge); + } + return new java.util.ArrayList<>(newTargets); + } + + private java.util.Set getExistingTargetLabels() { + java.util.Set existingTargetLabels = new java.util.HashSet<>(); + org.eclipse.core.resources.IWorkspace workspace = + org.eclipse.core.resources.ResourcesPlugin.getWorkspace(); + for (org.eclipse.core.resources.IProject project : workspace.getRoot().getProjects()) { + if (!project.isOpen()) continue; + try { + if (!project.hasNature(BazelNature.NATURE_ID)) continue; + } catch (org.eclipse.core.runtime.CoreException e) { + continue; + } + List labels = TargetProjectMapping.readTargets(project); + existingTargetLabels.addAll(labels); + } + LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", + "Found " + existingTargetLabels.size() + " existing targets in " + workspace.getRoot().getProjects().length + " projects")); + return existingTargetLabels; + } + + private java.util.Set findNewTargets(String[] targets, java.util.Set existingTargetLabels) { + java.util.Set newTargets = new java.util.HashSet<>(); + if (targets != null) { + for (String target : targets) { + if (!existingTargetLabels.contains(target)) { + newTargets.add(target); + } + } + } + return newTargets; + } + + private void createProjectsForTargets(String workspacePath, java.util.Set newTargets, BazelBridge bridge) { + LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", + "Creating projects for " + newTargets.size() + " new targets: " + newTargets)); + for (String targetLabel : newTargets) { + try { + String packagePath = LabelUtils.extractPackageName(targetLabel); + boolean isTestTarget = bridge.isTestTarget(targetLabel); + org.eclipse.core.resources.IProject project = + BazelProjectCreator.createProjectForPackage( + workspacePath, packagePath, targetLabel, null, true, isTestTarget); + if (project != null) { + LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", + "Created project for target: " + targetLabel)); + } + } catch (Exception e) { + LOG.log(new Status(IStatus.WARNING, "com.bazel.jdt", + "Failed to create project for target: " + targetLabel, e)); + } + } + } + private Object handleSyncProject(List arguments) { try { if (!arguments.isEmpty() && arguments.get(0) instanceof String) { From 0481a7c34f183eebfbfc1215fa94f2878dabe61b Mon Sep 17 00:00:00 2001 From: Duy Bui Date: Sat, 30 May 2026 10:58:15 +0700 Subject: [PATCH 2/3] Add hint to clean after reimport --- bazel-jdt-bridge/vscode-extension/src/extension.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/bazel-jdt-bridge/vscode-extension/src/extension.ts b/bazel-jdt-bridge/vscode-extension/src/extension.ts index d53d63c..7fd87c3 100644 --- a/bazel-jdt-bridge/vscode-extension/src/extension.ts +++ b/bazel-jdt-bridge/vscode-extension/src/extension.ts @@ -105,7 +105,18 @@ function activateFull(context: vscode.ExtensionContext, workspaceRoot: string) { } refreshTestDiscovery(); - vscode.window.showInformationMessage('Bazel project re-imported (scope changed)'); + const action = await vscode.window.showInformationMessage( + 'Bazel project re-imported (scope changed). If Java features don\'t work correctly, please run "Java: Clean Java Language Server Workspace" for a full reload', + 'Clean now', + 'Dismiss' + ); + if (action === 'Clean now') { + try { + await vscode.commands.executeCommand('java.clean.workspace'); + } catch (error) { + vscode.window.showErrorMessage(`Failed to clean workspace: ${error}`); + } + } } catch { // Silently ignore — re-import is best-effort } From 4444c04998fdf7045facdc2f89a6b57c491c018d Mon Sep 17 00:00:00 2001 From: Duy Bui Date: Mon, 1 Jun 2026 10:32:54 +0700 Subject: [PATCH 3/3] refactor --- .../com/bazel/jdt/BazelCommandHandler.java | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java index c3d0f27..7545db1 100644 --- a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java +++ b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelCommandHandler.java @@ -1,9 +1,14 @@ package com.bazel.jdt; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourcesPlugin; +import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; @@ -12,6 +17,7 @@ import org.eclipse.jdt.ls.core.internal.IDelegateCommandHandler; import org.eclipse.jdt.ls.core.internal.JobHelpers; + public class BazelCommandHandler implements IDelegateCommandHandler { private static final ILog LOG = Platform.getLog(BazelCommandHandler.class); static final String DEFAULT_CACHE_DIR = System.getProperty("user.home", "") + "/.cache/bazel-jdt"; @@ -113,9 +119,9 @@ private Object handleImportProject(List arguments) { } } - private java.util.List createProjectsForNewTargets(String workspacePath, String[] targets, BazelBridge bridge) { - java.util.Set existingTargetLabels = getExistingTargetLabels(); - java.util.Set newTargets = findNewTargets(targets, existingTargetLabels); + private List createProjectsForNewTargets(String workspacePath, String[] targets, BazelBridge bridge) { + Set existingTargetLabels = getExistingTargetLabels(); + Set newTargets = findNewTargets(targets, existingTargetLabels); LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", "Discovered " + newTargets.size() + " new targets (existing: " + existingTargetLabels.size() + ")")); @@ -123,18 +129,17 @@ private java.util.List createProjectsForNewTargets(String workspacePath, if (!newTargets.isEmpty()) { createProjectsForTargets(workspacePath, newTargets, bridge); } - return new java.util.ArrayList<>(newTargets); + return new ArrayList<>(newTargets); } - private java.util.Set getExistingTargetLabels() { - java.util.Set existingTargetLabels = new java.util.HashSet<>(); - org.eclipse.core.resources.IWorkspace workspace = - org.eclipse.core.resources.ResourcesPlugin.getWorkspace(); - for (org.eclipse.core.resources.IProject project : workspace.getRoot().getProjects()) { + private Set getExistingTargetLabels() { + Set existingTargetLabels = new HashSet<>(); + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + for (IProject project : workspace.getRoot().getProjects()) { if (!project.isOpen()) continue; try { if (!project.hasNature(BazelNature.NATURE_ID)) continue; - } catch (org.eclipse.core.runtime.CoreException e) { + } catch (CoreException e) { continue; } List labels = TargetProjectMapping.readTargets(project); @@ -145,8 +150,8 @@ private java.util.Set getExistingTargetLabels() { return existingTargetLabels; } - private java.util.Set findNewTargets(String[] targets, java.util.Set existingTargetLabels) { - java.util.Set newTargets = new java.util.HashSet<>(); + private Set findNewTargets(String[] targets, Set existingTargetLabels) { + Set newTargets = new HashSet<>(); if (targets != null) { for (String target : targets) { if (!existingTargetLabels.contains(target)) { @@ -157,14 +162,14 @@ private java.util.Set findNewTargets(String[] targets, java.util.Set newTargets, BazelBridge bridge) { + private void createProjectsForTargets(String workspacePath, Set newTargets, BazelBridge bridge) { LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", "Creating projects for " + newTargets.size() + " new targets: " + newTargets)); for (String targetLabel : newTargets) { try { String packagePath = LabelUtils.extractPackageName(targetLabel); boolean isTestTarget = bridge.isTestTarget(targetLabel); - org.eclipse.core.resources.IProject project = + IProject project = BazelProjectCreator.createProjectForPackage( workspacePath, packagePath, targetLabel, null, true, isTestTarget); if (project != null) {