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..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"; @@ -98,7 +104,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 +119,70 @@ private Object handleImportProject(List arguments) { } } + 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() + ")")); + + if (!newTargets.isEmpty()) { + createProjectsForTargets(workspacePath, newTargets, bridge); + } + return new ArrayList<>(newTargets); + } + + 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 (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 Set findNewTargets(String[] targets, Set existingTargetLabels) { + Set newTargets = new HashSet<>(); + if (targets != null) { + for (String target : targets) { + if (!existingTargetLabels.contains(target)) { + newTargets.add(target); + } + } + } + return newTargets; + } + + 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); + 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) { 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 }