diff --git a/bazel-jdt-bridge/config.json b/bazel-jdt-bridge/config.json new file mode 100644 index 0000000..276a4f4 --- /dev/null +++ b/bazel-jdt-bridge/config.json @@ -0,0 +1,6 @@ +{ + "baseDir": ".bazel-jdt", + "configFile": ".bazelproject", + "projectsDir": "projects", + "aspectsDir": "aspects" +} diff --git a/bazel-jdt-bridge/crates/bazel-jdt-core/src/aspect.rs b/bazel-jdt-bridge/crates/bazel-jdt-core/src/aspect.rs index d88ba66..3f7dc1a 100644 --- a/bazel-jdt-bridge/crates/bazel-jdt-core/src/aspect.rs +++ b/bazel-jdt-bridge/crates/bazel-jdt-core/src/aspect.rs @@ -10,7 +10,9 @@ pub enum AspectError { Utf8Error(#[from] std::string::FromUtf8Error), } -const ASPECT_DIR_NAME: &str = ".bazel-jdt/aspects"; +fn aspect_dir_name() -> String { + crate::internal_config::aspects_dir() +} const VERSION_FILE: &str = ".version"; const ASPECT_BUILD: &str = ""; @@ -113,7 +115,8 @@ pub fn version_hash(bazel_major: u32) -> String { /// what's already on disk. Returns the workspace-relative Bazel aspect label. pub fn extract_if_needed(workspace_root: &Path, bazel_path: &str) -> Result { let bazel_major = detect_bazel_major_version(bazel_path); - let aspect_dir = workspace_root.join(ASPECT_DIR_NAME); + let dir_name = aspect_dir_name(); + let aspect_dir = workspace_root.join(&dir_name); let version_path = aspect_dir.join(VERSION_FILE); let current_hash = version_hash(bazel_major); @@ -146,7 +149,7 @@ pub fn extract_if_needed(workspace_root: &Path, bazel_path: &str) -> Result Result Option { let bazelignore_path = workspace_root.join(".bazelignore"); let contents = fs::read_to_string(&bazelignore_path).ok()?; + let base_dir = crate::internal_config::base_dir(); + let dir_name = aspect_dir_name(); for line in contents.lines() { let line = line.trim(); if line.is_empty() || line.starts_with('#') { continue; } - if line == ".bazel-jdt" || line == ".bazel-jdt/" || line == ".bazel-jdt/**" || line == "/" { + if line == base_dir + || line == format!("{}/", base_dir) + || line == format!("{}/**", base_dir) + || line == "/" + { return Some(format!( "Aspect directory '{}' is covered by .bazelignore \ (pattern: '{}') — aspects may not be found by Bazel. \ Please remove this pattern from .bazelignore.", - ASPECT_DIR_NAME, line + dir_name, line )); } } @@ -201,9 +210,12 @@ mod tests { let label = extract_if_needed(tmp.path(), "bazel").unwrap(); assert!(label.contains("intellij_info_bundled.bzl%intellij_info_aspect")); - assert!(label.starts_with("//.bazel-jdt/aspects:intellij_info_bundled.bzl")); + assert!(label.starts_with(&format!( + "//{}:intellij_info_bundled.bzl", + aspect_dir_name() + ))); - let aspect_dir = tmp.path().join(ASPECT_DIR_NAME); + let aspect_dir = tmp.path().join(aspect_dir_name()); assert!(aspect_dir.join("BUILD").exists()); assert!(aspect_dir.join("intellij_info_bundled.bzl").exists()); assert!(aspect_dir.join("intellij_info_impl_bundled.bzl").exists()); @@ -223,7 +235,7 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); extract_if_needed(tmp.path(), "bazel").unwrap(); - let version_path = tmp.path().join(ASPECT_DIR_NAME).join(VERSION_FILE); + let version_path = tmp.path().join(aspect_dir_name()).join(VERSION_FILE); std::thread::sleep(std::time::Duration::from_millis(10)); extract_if_needed(tmp.path(), "bazel").unwrap(); @@ -235,7 +247,7 @@ mod tests { #[test] fn test_extract_updates_when_version_differs() { let tmp = tempfile::tempdir().unwrap(); - let aspect_dir = tmp.path().join(ASPECT_DIR_NAME); + let aspect_dir = tmp.path().join(aspect_dir_name()); extract_if_needed(tmp.path(), "bazel").unwrap(); diff --git a/bazel-jdt-bridge/crates/bazel-jdt-core/src/internal_config.rs b/bazel-jdt-bridge/crates/bazel-jdt-core/src/internal_config.rs new file mode 100644 index 0000000..40afe7b --- /dev/null +++ b/bazel-jdt-bridge/crates/bazel-jdt-core/src/internal_config.rs @@ -0,0 +1,38 @@ +const CONFIG_JSON: &str = include_str!("../../../config.json"); + +fn extract_json_str<'a>(json: &'a str, key: &str) -> Option<&'a str> { + let needle = format!("\"{}\"", key); + let after_key = json.split(&needle).nth(1)?; + let after_colon = after_key.split_once(':')?.1.trim(); + let after_quote = after_colon.strip_prefix('"')?; + let value = after_quote.split('"').next()?; + Some(value) +} + +pub fn base_dir() -> &'static str { + extract_json_str(CONFIG_JSON, "baseDir").unwrap_or(".bazel-jdt") +} + +pub fn config_file() -> &'static str { + extract_json_str(CONFIG_JSON, "configFile").unwrap_or(".bazelproject") +} + +pub fn aspects_dir() -> String { + format!( + "{}/{}", + base_dir(), + extract_json_str(CONFIG_JSON, "aspectsDir").unwrap_or("aspects") + ) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_config_reads_from_root_config_json() { + assert_eq!(base_dir(), ".bazel-jdt"); + assert_eq!(config_file(), ".bazelproject"); + assert_eq!(aspects_dir(), ".bazel-jdt/aspects"); + } +} diff --git a/bazel-jdt-bridge/crates/bazel-jdt-core/src/lib.rs b/bazel-jdt-bridge/crates/bazel-jdt-core/src/lib.rs index a1087f9..0e27f74 100644 --- a/bazel-jdt-bridge/crates/bazel-jdt-core/src/lib.rs +++ b/bazel-jdt-bridge/crates/bazel-jdt-core/src/lib.rs @@ -1,5 +1,6 @@ pub mod aspect; pub mod change_detector; +pub mod internal_config; pub mod jni_exports; pub mod state; pub mod watcher; diff --git a/bazel-jdt-bridge/crates/bazel-jdt-core/src/watcher.rs b/bazel-jdt-bridge/crates/bazel-jdt-core/src/watcher.rs index 1d19b36..fd6bf38 100644 --- a/bazel-jdt-bridge/crates/bazel-jdt-core/src/watcher.rs +++ b/bazel-jdt-bridge/crates/bazel-jdt-core/src/watcher.rs @@ -37,7 +37,7 @@ impl BuildFileWatcher { let mut debouncer = notify_debouncer_full::new_debouncer(Duration::from_millis(500), None, tx)?; - // Watch workspace root non-recursively for WORKSPACE and .bazelproject changes + // Watch workspace root non-recursively for WORKSPACE changes if let Err(e) = debouncer.watch(&workspace_root, RecursiveMode::NonRecursive) { if cfg!(target_os = "linux") { log::warn!( @@ -48,6 +48,18 @@ impl BuildFileWatcher { return Err(WatcherError::NotifyError(e)); } + // Watch base dir non-recursively for .bazelproject changes + let bazel_jdt_dir = workspace_root.join(crate::internal_config::base_dir()); + if bazel_jdt_dir.is_dir() { + if let Err(e) = debouncer.watch(&bazel_jdt_dir, RecursiveMode::NonRecursive) { + log::warn!( + "Failed to watch {} directory: {}", + crate::internal_config::base_dir(), + e + ); + } + } + // Watch each user-selected directory recursively for BUILD file changes for rel_path in &watch_paths { let abs_path = workspace_root.join(rel_path); @@ -196,17 +208,26 @@ pub fn is_watched_file(path: &Path) -> bool { .map(|name| { matches!( name, - "BUILD" | "BUILD.bazel" | "WORKSPACE" | "WORKSPACE.bazel" | ".bazelproject" - ) + "BUILD" | "BUILD.bazel" | "WORKSPACE" | "WORKSPACE.bazel" + ) || is_bazelproject_file(path) }) .unwrap_or(false) } +fn is_in_bazel_jdt_dir(path: &Path) -> bool { + path.parent() + .and_then(|p| p.file_name()) + .and_then(|n| n.to_str()) + .map(|n| n == crate::internal_config::base_dir()) + .unwrap_or(false) +} + pub fn is_bazelproject_file(path: &Path) -> bool { path.file_name() .and_then(|name| name.to_str()) - .map(|name| name == ".bazelproject") + .map(|name| name == crate::internal_config::config_file()) .unwrap_or(false) + && is_in_bazel_jdt_dir(path) } impl Drop for BuildFileWatcher { @@ -240,8 +261,10 @@ mod tests { assert!(is_watched_file(Path::new("WORKSPACE.bazel"))); assert!(is_watched_file(Path::new("/some/path/BUILD"))); assert!(is_watched_file(Path::new("/some/path/BUILD.bazel"))); - assert!(is_watched_file(Path::new(".bazelproject"))); - assert!(is_watched_file(Path::new("/some/path/.bazelproject"))); + assert!(is_watched_file(Path::new(".bazel-jdt/.bazelproject"))); + assert!(is_watched_file(Path::new( + "/some/path/.bazel-jdt/.bazelproject" + ))); } #[test] @@ -252,12 +275,19 @@ mod tests { assert!(!is_watched_file(Path::new("Cargo.toml"))); assert!(!is_watched_file(Path::new("src/main.rs"))); assert!(!is_watched_file(Path::new(""))); + // .bazelproject at root (wrong location) should not be watched + assert!(!is_watched_file(Path::new(".bazelproject"))); + assert!(!is_watched_file(Path::new("/workspace/.bazelproject"))); } #[test] fn test_is_bazelproject_file() { - assert!(is_bazelproject_file(Path::new(".bazelproject"))); - assert!(is_bazelproject_file(Path::new("/workspace/.bazelproject"))); + assert!(is_bazelproject_file(Path::new(".bazel-jdt/.bazelproject"))); + assert!(is_bazelproject_file(Path::new( + "/workspace/.bazel-jdt/.bazelproject" + ))); + assert!(!is_bazelproject_file(Path::new(".bazelproject"))); + assert!(!is_bazelproject_file(Path::new("/workspace/.bazelproject"))); assert!(!is_bazelproject_file(Path::new("BUILD"))); assert!(!is_bazelproject_file(Path::new("WORKSPACE"))); assert!(!is_bazelproject_file(Path::new(""))); diff --git a/bazel-jdt-bridge/java-bridge/bnd.bnd b/bazel-jdt-bridge/java-bridge/bnd.bnd index 33db071..54fc275 100644 --- a/bazel-jdt-bridge/java-bridge/bnd.bnd +++ b/bazel-jdt-bridge/java-bridge/bnd.bnd @@ -15,7 +15,7 @@ Import-Package: \ org.osgi.framework.hooks.weaving, \ * Export-Package: com.bazel.jdt -Private-Package: org.objectweb.asm,org.objectweb.asm.signature +Private-Package: org.objectweb.asm,org.objectweb.asm.signature,org.json Bundle-NativeCode: \ native/linux-x86_64/libbazel_jdt_core.so; osname=Linux; processor=x86_64, \ native/linux-aarch64/libbazel_jdt_core.so; osname=Linux; processor=aarch64, \ diff --git a/bazel-jdt-bridge/java-bridge/pom.xml b/bazel-jdt-bridge/java-bridge/pom.xml index 12b109e..1c51f2a 100644 --- a/bazel-jdt-bridge/java-bridge/pom.xml +++ b/bazel-jdt-bridge/java-bridge/pom.xml @@ -62,6 +62,11 @@ 9.7 compile + + org.json + json + 20240303 + junit junit @@ -71,6 +76,17 @@ + + + ${project.basedir}/.. + + config.json + + + + src/main/resources + + org.apache.maven.plugins diff --git a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelBuildSupport.java b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelBuildSupport.java index 9fc718e..d31ed5b 100644 --- a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelBuildSupport.java +++ b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelBuildSupport.java @@ -24,7 +24,7 @@ public class BazelBuildSupport implements IBuildSupport { "**/BUILD.bazel", "**/WORKSPACE", "**/WORKSPACE.bazel", - "**/.bazelproject" + "**/" + InternalConfig.bazelprojectRelPath() ); private static final ConcurrentLinkedQueue pendingChangedFiles = new ConcurrentLinkedQueue<>(); diff --git a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectCreator.java b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectCreator.java index 01c1590..5c446d4 100644 --- a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectCreator.java +++ b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectCreator.java @@ -55,7 +55,7 @@ public static IProject createProjectForPackage( IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IProject project = workspaceRoot.getProject(projectName); - File bazelProjectDir = new File(workspacePath, ".bazel-projects/" + projectName); + File bazelProjectDir = new File(workspacePath, InternalConfig.projectsDirRelPath() + "/" + projectName); IPath expectedLocation = new Path(bazelProjectDir.getAbsolutePath()); if (project.exists()) { @@ -66,17 +66,17 @@ public static IProject createProjectForPackage( TargetProjectMapping.appendTargets(project, Collections.singletonList(targetLabel)); } LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", - "Project '" + projectName + "' already at .bazel-projects/, skipping rebuild")); + "Project '" + projectName + "' already at " + InternalConfig.projectsDirRelPath() + "/, skipping rebuild")); return project; } LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", - "Migrating project '" + projectName + "' to .bazel-projects/ location")); + "Migrating project '" + projectName + "' to " + InternalConfig.projectsDirRelPath() + "/ location")); project.delete(false, true, monitor); } if (!bazelProjectDir.exists() && !bazelProjectDir.mkdirs()) { LOG.log(new Status(IStatus.ERROR, "com.bazel.jdt", - "Failed to create .bazel-projects directory: " + bazelProjectDir.getAbsolutePath())); + "Failed to create projects directory: " + bazelProjectDir.getAbsolutePath())); return null; } diff --git a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectImporter.java b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectImporter.java index 7154265..bc10690 100644 --- a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectImporter.java +++ b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectImporter.java @@ -1,6 +1,8 @@ package com.bazel.jdt; import java.io.File; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; import java.util.Hashtable; import org.eclipse.core.resources.IProject; @@ -30,7 +32,7 @@ public boolean applies(IProgressMonitor monitor) { boolean hasWorkspace = new File(rootFolder, "WORKSPACE").exists() || new File(rootFolder, "WORKSPACE.bazel").exists(); if (!hasWorkspace) return false; - return new File(rootFolder, ".bazelproject").exists(); + return new File(rootFolder, InternalConfig.bazelprojectRelPath()).exists(); } @Override @@ -62,10 +64,11 @@ public void importToWorkspace(IProgressMonitor monitor) throws CoreException { } bridge.initialize(workspacePath, bazelPath, cacheDir); + LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", "Importing Bazel workspace: " + workspacePath)); - ensureBazelProjectsGitignore(workspacePath); + ensureProjectGitignore(workspacePath); if (projectView != null && !projectView.getDirectories().isEmpty()) { String[] watchDirs = projectView.getDirectories().toArray(new String[0]); @@ -273,7 +276,7 @@ private boolean tryFastReload(IProgressMonitor monitor) throws CoreException { bridge.setProjectView(projectView); } - ensureBazelProjectsGitignore(workspacePath); + ensureProjectGitignore(workspacePath); if (projectView != null && !projectView.getDirectories().isEmpty()) { String[] watchDirs = projectView.getDirectories().toArray(new String[0]); @@ -325,31 +328,18 @@ public void run(IProgressMonitor pm) throws CoreException { return true; } - private static void ensureBazelProjectsGitignore(String workspacePath) { - File gitignore = new File(workspacePath, ".gitignore"); - String entry = ".bazel-projects/"; + private static void ensureProjectGitignore(String workspacePath) { + File gitignore = new File(workspacePath, InternalConfig.BASE_DIR + "/.gitignore"); + if (gitignore.exists()) return; try { - if (gitignore.exists()) { - String content = new String(java.nio.file.Files.readAllBytes(gitignore.toPath()), - java.nio.charset.StandardCharsets.UTF_8); - for (String line : content.split("\n")) { - if (line.trim().equals(entry)) { - return; - } - } - String separator = content.endsWith("\n") ? "" : "\n"; - java.nio.file.Files.write(gitignore.toPath(), - (separator + entry + "\n").getBytes(java.nio.charset.StandardCharsets.UTF_8), - java.nio.file.StandardOpenOption.APPEND); - } else { - java.nio.file.Files.write(gitignore.toPath(), - (entry + "\n").getBytes(java.nio.charset.StandardCharsets.UTF_8)); - } + gitignore.getParentFile().mkdirs(); + Files.write(gitignore.toPath(), + "*\n".getBytes(StandardCharsets.UTF_8)); LOG.log(new Status(IStatus.INFO, "com.bazel.jdt", - "Added .bazel-projects/ to .gitignore")); + "Created " + InternalConfig.BASE_DIR + "/.gitignore")); } catch (Exception e) { LOG.log(new Status(IStatus.WARNING, "com.bazel.jdt", - "Failed to update .gitignore: " + e.getMessage())); + "Failed to create .gitignore: " + e.getMessage())); } } diff --git a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectView.java b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectView.java index f021aca..eb6fae7 100644 --- a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectView.java +++ b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/BazelProjectView.java @@ -20,7 +20,7 @@ */ public final class BazelProjectView { private static final ILog LOG = Platform.getLog(BazelProjectView.class); - private static final String BAZELPROJECT_FILE = ".bazelproject"; + private static final String BAZELPROJECT_FILE = InternalConfig.bazelprojectRelPath(); private final List directories = new ArrayList<>(); private final List targets = new ArrayList<>(); diff --git a/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/InternalConfig.java b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/InternalConfig.java new file mode 100644 index 0000000..f116642 --- /dev/null +++ b/bazel-jdt-bridge/java-bridge/src/main/java/com/bazel/jdt/InternalConfig.java @@ -0,0 +1,44 @@ +package com.bazel.jdt; + +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import org.json.JSONObject; + +public final class InternalConfig { + public static final String BASE_DIR; + public static final String CONFIG_FILE; + public static final String PROJECTS_DIR; + public static final String ASPECTS_DIR; + + static { + String baseDir = ".bazel-jdt"; + String configFile = ".bazelproject"; + String projectsDir = "projects"; + String aspectsDir = "aspects"; + try (InputStream in = InternalConfig.class.getClassLoader().getResourceAsStream("config.json")) { + if (in != null) { + JSONObject obj = new JSONObject(new String(in.readAllBytes(), StandardCharsets.UTF_8)); + baseDir = obj.optString("baseDir", baseDir); + configFile = obj.optString("configFile", configFile); + projectsDir = obj.optString("projectsDir", projectsDir); + aspectsDir = obj.optString("aspectsDir", aspectsDir); + } + } catch (Exception e) { + System.err.println("[bazel-jdt] Failed to load config.json, using defaults: " + e.getMessage()); + } + BASE_DIR = baseDir; + CONFIG_FILE = configFile; + PROJECTS_DIR = projectsDir; + ASPECTS_DIR = aspectsDir; + } + + private InternalConfig() {} + + public static String bazelprojectRelPath() { + return BASE_DIR + "/" + CONFIG_FILE; + } + + public static String projectsDirRelPath() { + return BASE_DIR + "/" + PROJECTS_DIR; + } +} diff --git a/bazel-jdt-bridge/java-bridge/src/test/java/com/bazel/jdt/BazelProjectViewTest.java b/bazel-jdt-bridge/java-bridge/src/test/java/com/bazel/jdt/BazelProjectViewTest.java index f9d0742..4a0e6f2 100644 --- a/bazel-jdt-bridge/java-bridge/src/test/java/com/bazel/jdt/BazelProjectViewTest.java +++ b/bazel-jdt-bridge/java-bridge/src/test/java/com/bazel/jdt/BazelProjectViewTest.java @@ -17,7 +17,9 @@ public class BazelProjectViewTest { public TemporaryFolder tempFolder = new TemporaryFolder(); private File writeBazelproject(String content) throws IOException { - File file = new File(tempFolder.getRoot(), ".bazelproject"); + File bazelJdtDir = new File(tempFolder.getRoot(), InternalConfig.BASE_DIR); + bazelJdtDir.mkdirs(); + File file = new File(bazelJdtDir, InternalConfig.CONFIG_FILE); try (FileWriter writer = new FileWriter(file)) { writer.write(content); } diff --git a/bazel-jdt-bridge/java-bridge/src/test/java/com/bazel/jdt/InternalConfigTest.java b/bazel-jdt-bridge/java-bridge/src/test/java/com/bazel/jdt/InternalConfigTest.java new file mode 100644 index 0000000..61d0a12 --- /dev/null +++ b/bazel-jdt-bridge/java-bridge/src/test/java/com/bazel/jdt/InternalConfigTest.java @@ -0,0 +1,25 @@ +package com.bazel.jdt; + +import static org.junit.Assert.*; +import org.junit.Test; + +public class InternalConfigTest { + + @Test + public void testConstants() { + assertEquals(".bazel-jdt", InternalConfig.BASE_DIR); + assertEquals(".bazelproject", InternalConfig.CONFIG_FILE); + assertEquals("projects", InternalConfig.PROJECTS_DIR); + assertEquals("aspects", InternalConfig.ASPECTS_DIR); + } + + @Test + public void testBazelprojectRelPath() { + assertEquals(".bazel-jdt/.bazelproject", InternalConfig.bazelprojectRelPath()); + } + + @Test + public void testProjectsDirRelPath() { + assertEquals(".bazel-jdt/projects", InternalConfig.projectsDirRelPath()); + } +} diff --git a/bazel-jdt-bridge/vscode-extension/bazel-jdt-bridge-0.1.0-pre.5.vsix b/bazel-jdt-bridge/vscode-extension/bazel-jdt-bridge-0.1.0-pre.5.vsix new file mode 100644 index 0000000..86a827c Binary files /dev/null and b/bazel-jdt-bridge/vscode-extension/bazel-jdt-bridge-0.1.0-pre.5.vsix differ diff --git a/bazel-jdt-bridge/vscode-extension/src/extension.ts b/bazel-jdt-bridge/vscode-extension/src/extension.ts index 3d728f3..7d04cbf 100644 --- a/bazel-jdt-bridge/vscode-extension/src/extension.ts +++ b/bazel-jdt-bridge/vscode-extension/src/extension.ts @@ -6,6 +6,9 @@ import { BazelDebugConfigurationProvider } from './debugAdapter'; import { createStatusBar } from './statusBar'; import { getConfig } from './config'; import { parseBazelprojectFile, resolveScopePatterns } from './bazelproject'; +import internalConfig from '../../config.json'; + +const BAZELPROJECT_REL_PATH = path.join(internalConfig.baseDir, internalConfig.configFile); export async function activate(context: vscode.ExtensionContext) { const workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath; @@ -19,7 +22,7 @@ export async function activate(context: vscode.ExtensionContext) { return; } - const bazelprojectPath = path.join(workspaceRoot, '.bazelproject'); + const bazelprojectPath = path.join(workspaceRoot, BAZELPROJECT_REL_PATH); const hasBazelproject = fs.existsSync(bazelprojectPath); if (hasBazelproject) { @@ -60,7 +63,7 @@ function activateFull(context: vscode.ExtensionContext, workspaceRoot: string) { let dependencyPackageCache: string[] = []; - const bazelprojectPattern = new vscode.RelativePattern(workspaceRoot, '.bazelproject'); + const bazelprojectPattern = new vscode.RelativePattern(workspaceRoot, BAZELPROJECT_REL_PATH); const watcher = vscode.workspace.createFileSystemWatcher(bazelprojectPattern); let debounceTimer: ReturnType | undefined; let wizardActive = false; @@ -84,7 +87,7 @@ function activateFull(context: vscode.ExtensionContext, workspaceRoot: string) { } const config = getConfig(); - const viewConfig = parseBazelprojectFile(path.join(workspaceRoot, '.bazelproject')); + const viewConfig = parseBazelprojectFile(path.join(workspaceRoot, BAZELPROJECT_REL_PATH)); const patterns = viewConfig ? resolveScopePatterns(viewConfig) : []; const buildFlags = viewConfig ? viewConfig.buildFlags : []; const bazelPath = viewConfig?.bazelBinary || config.bazelPath; @@ -171,7 +174,7 @@ function activateFull(context: vscode.ExtensionContext, workspaceRoot: string) { } function setupCreationOnlyWatcher(context: vscode.ExtensionContext, workspaceRoot: string) { - const pattern = new vscode.RelativePattern(workspaceRoot, '.bazelproject'); + const pattern = new vscode.RelativePattern(workspaceRoot, BAZELPROJECT_REL_PATH); const watcher = vscode.workspace.createFileSystemWatcher(pattern); context.subscriptions.push( diff --git a/bazel-jdt-bridge/vscode-extension/src/importWizard.ts b/bazel-jdt-bridge/vscode-extension/src/importWizard.ts index c9caf68..4f7389f 100644 --- a/bazel-jdt-bridge/vscode-extension/src/importWizard.ts +++ b/bazel-jdt-bridge/vscode-extension/src/importWizard.ts @@ -3,6 +3,10 @@ import * as path from 'path'; import * as fs from 'fs'; import { parseBazelprojectFile, resolveScopePatterns } from './bazelproject'; import { getConfig } from './config'; +import internalConfig from '../../config.json'; + +const BAZEL_JDT_DIR_REL = internalConfig.baseDir; +const BAZELPROJECT_REL_PATH = path.join(internalConfig.baseDir, internalConfig.configFile); export interface ImportWizardResult { strategy: 'existing' | 'manual' | 'everything'; @@ -220,7 +224,11 @@ async function runDirectoryPicker( ); if (saveChoice && saveChoice.label.startsWith('Yes')) { - const bazelprojectPath = path.join(workspaceRoot, '.bazelproject'); + const bazelJdtDir = path.join(workspaceRoot, BAZEL_JDT_DIR_REL); + if (!fs.existsSync(bazelJdtDir)) { + fs.mkdirSync(bazelJdtDir, { recursive: true }); + } + const bazelprojectPath = path.join(workspaceRoot, BAZELPROJECT_REL_PATH); const content = generateBazelprojectContent(options); vscode.commands.executeCommand('_bazel-jdt.setWizardActive', true); fs.writeFileSync(bazelprojectPath, content, 'utf-8'); @@ -504,12 +512,6 @@ function generateBazelprojectContent(options: BazelprojectOptions): string { } function findBazelprojectFile(workspaceRoot: string): string | undefined { - const candidates = ['.bazelproject']; - for (const name of candidates) { - const fullPath = path.join(workspaceRoot, name); - if (fs.existsSync(fullPath)) { - return fullPath; - } - } - return undefined; + const fullPath = path.join(workspaceRoot, BAZELPROJECT_REL_PATH); + return fs.existsSync(fullPath) ? fullPath : undefined; } diff --git a/bazel-jdt-bridge/vscode-extension/tsconfig.json b/bazel-jdt-bridge/vscode-extension/tsconfig.json index fbb3c62..25244fb 100644 --- a/bazel-jdt-bridge/vscode-extension/tsconfig.json +++ b/bazel-jdt-bridge/vscode-extension/tsconfig.json @@ -12,7 +12,8 @@ "skipLibCheck": true, "forceConsistentCasingInFileNames": true, "declaration": true, - "sourceMap": true + "sourceMap": true, + "resolveJsonModule": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"]