fix(lsp): resolve JDTLS root to topmost pom.xml in Java Maven multi-module projects (#28761)
deploy / deploy (push) Has been cancelled
nix-eval / nix-eval (push) Has been cancelled
nix-hashes / compute-hash (blacksmith-4vcpu-ubuntu-2404, x86_64-linux) (push) Has been cancelled
nix-hashes / compute-hash (blacksmith-4vcpu-ubuntu-2404-arm, aarch64-linux) (push) Has been cancelled
nix-hashes / compute-hash (macos-15-intel, x86_64-darwin) (push) Has been cancelled
nix-hashes / compute-hash (macos-latest, aarch64-darwin) (push) Has been cancelled
nix-hashes / update-hashes (push) Has been cancelled
publish / version (push) Has been cancelled
publish / build-cli (push) Has been cancelled
publish / sign-cli-windows (push) Has been cancelled
publish / build-electron (map[bun_install_flags:--os=darwin --cpu=arm64 host:macos-26 platform_flag:--mac --arm64 target:aarch64-apple-darwin]) (push) Has been cancelled
publish / build-electron (map[bun_install_flags:--os=darwin --cpu=x64 host:macos-26-intel platform_flag:--mac --x64 target:x86_64-apple-darwin]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-ubuntu-2404 platform_flag:--linux target:x86_64-unknown-linux-gnu]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-ubuntu-2404-arm platform_flag:--linux --arm64 target:aarch64-unknown-linux-gnu]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-windows-2025 platform_flag:--win target:x86_64-pc-windows-msvc]) (push) Has been cancelled
publish / build-electron (map[host:windows-2025 platform_flag:--win --arm64 target:aarch64-pc-windows-msvc]) (push) Has been cancelled
publish / publish (push) Has been cancelled
storybook / storybook build (push) Has been cancelled
generate / generate (push) Has been cancelled
typecheck / typecheck (push) Has been cancelled
deploy / deploy (push) Has been cancelled
nix-eval / nix-eval (push) Has been cancelled
nix-hashes / compute-hash (blacksmith-4vcpu-ubuntu-2404, x86_64-linux) (push) Has been cancelled
nix-hashes / compute-hash (blacksmith-4vcpu-ubuntu-2404-arm, aarch64-linux) (push) Has been cancelled
nix-hashes / compute-hash (macos-15-intel, x86_64-darwin) (push) Has been cancelled
nix-hashes / compute-hash (macos-latest, aarch64-darwin) (push) Has been cancelled
nix-hashes / update-hashes (push) Has been cancelled
publish / version (push) Has been cancelled
publish / build-cli (push) Has been cancelled
publish / sign-cli-windows (push) Has been cancelled
publish / build-electron (map[bun_install_flags:--os=darwin --cpu=arm64 host:macos-26 platform_flag:--mac --arm64 target:aarch64-apple-darwin]) (push) Has been cancelled
publish / build-electron (map[bun_install_flags:--os=darwin --cpu=x64 host:macos-26-intel platform_flag:--mac --x64 target:x86_64-apple-darwin]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-ubuntu-2404 platform_flag:--linux target:x86_64-unknown-linux-gnu]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-ubuntu-2404-arm platform_flag:--linux --arm64 target:aarch64-unknown-linux-gnu]) (push) Has been cancelled
publish / build-electron (map[host:blacksmith-4vcpu-windows-2025 platform_flag:--win target:x86_64-pc-windows-msvc]) (push) Has been cancelled
publish / build-electron (map[host:windows-2025 platform_flag:--win --arm64 target:aarch64-pc-windows-msvc]) (push) Has been cancelled
publish / publish (push) Has been cancelled
storybook / storybook build (push) Has been cancelled
generate / generate (push) Has been cancelled
typecheck / typecheck (push) Has been cancelled
Co-authored-by: Shoubhit Dash <shoubhit2005@gmail.com>
This commit is contained in:
@@ -55,6 +55,30 @@ const NearestRoot = (includePatterns: string[], excludePatterns?: string[]): Roo
|
||||
}
|
||||
}
|
||||
|
||||
const StrictNearestRoot = (includePatterns: string[], excludePatterns?: string[]): RootFunction => {
|
||||
return async (file, ctx) => {
|
||||
if (excludePatterns) {
|
||||
const excludedFiles = Filesystem.up({
|
||||
targets: excludePatterns,
|
||||
start: path.dirname(file),
|
||||
stop: ctx.directory,
|
||||
})
|
||||
const excluded = await excludedFiles.next()
|
||||
await excludedFiles.return()
|
||||
if (excluded.value) return undefined
|
||||
}
|
||||
const files = Filesystem.up({
|
||||
targets: includePatterns,
|
||||
start: path.dirname(file),
|
||||
stop: ctx.directory,
|
||||
})
|
||||
const first = await files.next()
|
||||
await files.return()
|
||||
if (!first.value) return undefined
|
||||
return path.dirname(first.value)
|
||||
}
|
||||
}
|
||||
|
||||
export interface Info {
|
||||
id: string
|
||||
extensions: string[]
|
||||
@@ -1173,31 +1197,63 @@ export const Astro: Info = {
|
||||
},
|
||||
}
|
||||
|
||||
function isModuleOf(pomContent: string, modulePath: string): boolean {
|
||||
const normalized = modulePath.replace(/\\/g, "/").replace(/\/$/, "")
|
||||
if (!normalized) return false
|
||||
const modulesBlocks = pomContent.match(/<modules>([\s\S]*?)<\/modules>/g) ?? []
|
||||
for (const block of modulesBlocks) {
|
||||
const stripped = block.replace(/<!--[\s\S]*?-->/g, "")
|
||||
for (const m of stripped.matchAll(/<module>\s*([^<]+?)\s*<\/module>/g)) {
|
||||
const decl = m[1].replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/$/, "")
|
||||
if (decl === normalized) return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
export const JDTLS: Info = {
|
||||
id: "jdtls",
|
||||
root: async (file, ctx) => {
|
||||
// Without exclusions, NearestRoot defaults to instance directory so we can't
|
||||
// distinguish between a) no project found and b) project found at instance dir.
|
||||
// So we can't choose the root from (potential) monorepo markers first.
|
||||
// Look for potential subproject markers first while excluding potential monorepo markers.
|
||||
const settingsMarkers = ["settings.gradle", "settings.gradle.kts"]
|
||||
const gradleMarkers = ["gradlew", "gradlew.bat"]
|
||||
const exclusionsForMonorepos = gradleMarkers.concat(settingsMarkers)
|
||||
|
||||
const [projectRoot, wrapperRoot, settingsRoot] = await Promise.all([
|
||||
NearestRoot(["pom.xml", "build.gradle", "build.gradle.kts", ".project", ".classpath"], exclusionsForMonorepos)(
|
||||
file,
|
||||
ctx,
|
||||
),
|
||||
NearestRoot(gradleMarkers, settingsMarkers)(file, ctx),
|
||||
NearestRoot(settingsMarkers)(file, ctx),
|
||||
// 1. Gradle (unchanged from original logic)
|
||||
const [wrapperRoot, settingsRoot] = await Promise.all([
|
||||
StrictNearestRoot(gradleMarkers, settingsMarkers)(file, ctx),
|
||||
StrictNearestRoot(settingsMarkers)(file, ctx),
|
||||
])
|
||||
|
||||
// If projectRoot is undefined we know we are in a monorepo or no project at all.
|
||||
// So can safely fall through to the other roots
|
||||
if (projectRoot) return projectRoot
|
||||
if (wrapperRoot) return wrapperRoot
|
||||
if (settingsRoot) return settingsRoot
|
||||
|
||||
// 2. Gradle single-project fallback (build.gradle without settings.gradle)
|
||||
const buildRoot = await StrictNearestRoot(["build.gradle", "build.gradle.kts"])(file, ctx)
|
||||
if (buildRoot) return buildRoot
|
||||
|
||||
// 3. Maven: walk up pom.xml chain verifying <module> relationships
|
||||
const pomFiles = await Filesystem.findUp(
|
||||
"pom.xml",
|
||||
path.dirname(file),
|
||||
ctx.directory,
|
||||
)
|
||||
if (pomFiles.length > 0) {
|
||||
let root = path.dirname(pomFiles[0])
|
||||
for (let i = 1; i < pomFiles.length; i++) {
|
||||
const parentDir = path.dirname(pomFiles[i])
|
||||
const rel = path.relative(parentDir, root)
|
||||
const content = await fs.readFile(pomFiles[i], "utf-8").catch(() => null)
|
||||
if (content && isModuleOf(content, rel)) {
|
||||
root = parentDir
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
return root
|
||||
}
|
||||
|
||||
// 4. Eclipse native project fallback
|
||||
const eclipseRoot = await StrictNearestRoot([".project", ".classpath"])(file, ctx)
|
||||
if (eclipseRoot) return eclipseRoot
|
||||
|
||||
return undefined
|
||||
},
|
||||
extensions: [".java"],
|
||||
async spawn(root, _ctx, flags) {
|
||||
|
||||
Reference in New Issue
Block a user