Eclipse LSP in Practice: When to Switch from JDT for Polyglot Projects
Eclipse's built-in LSP support replaces legacy per-language plugins for TypeScript, Python, YAML, and more. This post shows when to use LSP versus JDT, a concrete Gradle setup for mixed Java/TypeScript projects, and the memory trade-offs to watch.
25 Jul 2025, 12:15 UTC

The Problem: One IDE, Too Many Language Plugins
You open a repository that mixes Java services, TypeScript frontends, Python scripts, and a handful of YAML configs. Historically, Eclipse meant installing a separate plugin for each language — JDT for Java, DLTK for Ruby, PyDev for Python, and so on. Each plugin brought its own parser, indexer, and quirks. Maintenance lagged; the Ruby plugin hasn't seen a meaningful update since 2018.
Since Eclipse 2019-09 (4.13), the Language Server Protocol (LSP) support built into the platform (via org.eclipse.lsp4e and the Wild Web Developer extensions) lets you drop in standard language servers — typescript-language-server, pyright, yaml-language-server — and get completion, diagnostics, and go-to-definition without a dedicated Eclipse plugin. The question isn't whether it works; it's when to rely on LSP versus sticking with JDT for Java.
Where LSP Wins: Polyglot Without the Plugin Tax
For any language that lacks a mature JDT-style plugin — TypeScript, Python, Dockerfile, JSON Schema, YAML — LSP is now the default path. The Wild Web Developer bundle ships with embedded servers for web languages, so a fresh Eclipse 2023-09+ install gives you TypeScript and JSON support out of the box (Node.js 18+ is bundled). For Python, you add pyright via pip install pyright and point Eclipse at the executable.
Configuration lives in .settings/org.eclipse.lsp4e.prefs per workspace or project. Eclipse also reads VS Code's .vscode/settings.json, so you can share server paths and initialization options across editors. Example snippet for a project that needs a specific TypeScript version:
# .settings/org.eclipse.lsp4e.prefs
languageServerIds=typescript
typescript.command=/home/user/.nvm/versions/node/v20.11.0/bin/typescript-language-server
typescript.args=--stdio
typescript.initializationOptions={"preferences":{"importModuleSpecifier":"relative"}}
Paths using ${workspaceFolder} resolve after import; absolute paths break portability. Keep server install locations under version control (or a shared network drive) if your team works offline or behind a corporate proxy that blocks npm install.
Worked Example: Mixed Java/TypeScript Gradle Project
Create a Gradle project with a Java backend and a React frontend in src/main/typescript.
- Add the TypeScript plugin to
build.gradle.kts:plugins { id("com.github.node-gradle.node") version "3.3.0" } node { version = "20.11.0" download = true } tasks.named("npm_install") { args = listOf("install", "typescript-language-server@3.5.0", "typescript@5.3.0") } - Run
./gradlew npm_install eclipse. Theeclipsetask (from Buildship) generates.projectand.classpathand writes a.settings/org.eclipse.lsp4e.prefsthat points to the Gradle-managed Node installation. - Import the project in Eclipse (File → Import → Existing Gradle Project). Open a
.tsxfile. The Problems view should show TypeScript diagnostics without any.projectnature for TypeScript. - Verify the server started: Window → Show View → Other → Language Servers. You'll see
typescript-language-serverwith PID and memory usage (typically 120–250 MB).
If diagnostics don't appear, add -Dlsp4j.trace=VERBOSE to eclipse.ini, restart, and check the Error Log for LSP request/response traces. Common cause: the server executable isn't on PATH and the generated prefs point to a missing location.
Trade-off: Java Stays on JDT
JDT still outperforms jdt.ls (the Java LSP server) on large codebases. JDT's incremental compiler, hot code replace, and advanced refactorings (move type, extract interface, infer generic type arguments) are not replicated in LSP. LSP offers only textual edits and basic rename. For a pure Java module, keep JDT. For the TypeScript, Python, or YAML parts of the same workspace, LSP is the pragmatic choice.
Memory is the practical limiter. Each language server runs as a separate process (Node.js, Python, etc.) communicating over stdio. Expect 100–300 MB per server. On a machine with <16 GB RAM, running JDT plus three language servers can trigger GC pressure and UI freezes. Monitor with:
jcmd VM.native_memory summary
Look for "Language Server" entries. If you hit limits, disable servers for languages you're not actively editing (uncheck in Preferences → Language Servers) or increase -Xmx in eclipse.ini.
Actionable Closing
Adopt LSP for every non-Java language in your Eclipse workspace. Start by inventorying which languages currently use legacy plugins (DLTK, PyDev, PHP Development Tools). For each, find the maintained LSP server (ruby-lsp, pyright, intelephense) and add its install step to your build script or onboarding docs. Keep JDT for Java. Verify the setup by opening a mixed-language file and confirming diagnostics appear in the Problems view without a project nature. That's the signal the integration works.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.