LSP Configuration
This commit is contained in:
parent
4cb1328ad6
commit
3cd15d53a2
3 changed files with 219 additions and 10 deletions
173
Containerfile
173
Containerfile
|
|
@ -1,9 +1,35 @@
|
||||||
# OpenCode dev sandbox: rootless-Podman container with JDK 25, Node 24, pnpm,
|
# OpenCode dev sandbox: rootless-Podman container with JDK 25, Node 24, Go,
|
||||||
# git, curl, and a hash-pinned build of OpenCode (github.com/anomalyco/opencode).
|
# Rust, pnpm, git, curl, and a hash-pinned build of OpenCode
|
||||||
|
# (github.com/anomalyco/opencode).
|
||||||
#
|
#
|
||||||
# Built as three stages: JDK and Node are pulled from their official upstream
|
# Built as multi-stage: JDK, Node, Go, and Rust toolchains are pulled from
|
||||||
# images and copied (not apt-installed) into a slim Debian final stage, to
|
# their official upstream images and copied (not apt-installed) into a slim
|
||||||
# keep the image small while staying on a mainstream glibc distro.
|
# Debian final stage, to keep the image reasonably small while staying on a
|
||||||
|
# mainstream glibc distro.
|
||||||
|
#
|
||||||
|
# LSP support for OpenCode's built-in LSP client (off by default -- needs
|
||||||
|
# `"lsp": true` in opencode.json to actually turn on):
|
||||||
|
# - Go -> gopls, built from source against the pinned Go
|
||||||
|
# toolchain below.
|
||||||
|
# - Rust -> rust-analyzer, installed as a rustup
|
||||||
|
# component (same trust chain as the rest of the
|
||||||
|
# copied Rust toolchain). OpenCode has no
|
||||||
|
# auto-download fallback for this one, unlike
|
||||||
|
# gopls, so it must already be on PATH.
|
||||||
|
# - TypeScript/JavaScript -> typescript + typescript-language-server,
|
||||||
|
# installed as global npm packages; NODE_PATH
|
||||||
|
# below makes the global `typescript` package
|
||||||
|
# resolvable from any mounted project dir, even
|
||||||
|
# ones with no local node_modules.
|
||||||
|
# - Java -> jdtls, pre-baked (OpenCode has NO auto-download
|
||||||
|
# fallback for Java at all -- it must already be
|
||||||
|
# on PATH). No bin/jdtls ships upstream, so
|
||||||
|
# scripts/jdtls is a hand-written launcher
|
||||||
|
# wrapper, the same convention every other jdtls
|
||||||
|
# consumer (nvim-jdtls, mason.nvim, coc-java) uses.
|
||||||
|
# - Kotlin -> kotlin-lsp (JetBrains' official server),
|
||||||
|
# pre-baked. Ships its own bundled JetBrains
|
||||||
|
# Runtime, so it needs none of this image's JDK.
|
||||||
|
|
||||||
# ---- Stage: JDK source ------------------------------------------------------
|
# ---- Stage: JDK source ------------------------------------------------------
|
||||||
# JDK 24 is EOL (Adoptium stopped building it Sept 2025; no 24-jdk* images
|
# JDK 24 is EOL (Adoptium stopped building it Sept 2025; no 24-jdk* images
|
||||||
|
|
@ -17,6 +43,18 @@ FROM eclipse-temurin:25-jdk-noble AS jdk-source
|
||||||
# final base so glibc versions are identical -- no compatibility risk at all.
|
# final base so glibc versions are identical -- no compatibility risk at all.
|
||||||
FROM node:24-trixie-slim AS node-source
|
FROM node:24-trixie-slim AS node-source
|
||||||
|
|
||||||
|
# ---- Stage: Go source --------------------------------------------------------
|
||||||
|
# Full toolchain, not just a standalone LSP binary: gopls shells out to `go`
|
||||||
|
# itself and needs the standard library's source/type info to be useful --
|
||||||
|
# the same reason the JDK above is copied in whole rather than just a jar.
|
||||||
|
# Matched to Debian Trixie for the same glibc-alignment reason as node-source.
|
||||||
|
FROM golang:1.27.1-trixie AS go-source
|
||||||
|
|
||||||
|
# ---- Stage: Rust source -------------------------------------------------------
|
||||||
|
# Full toolchain, for the same reason as Go above -- rust-analyzer needs a
|
||||||
|
# real sysroot (std source + metadata) to do anything beyond bare syntax.
|
||||||
|
FROM rust:1.98.1-trixie AS rust-source
|
||||||
|
|
||||||
# ---- Final stage --------------------------------------------------------------
|
# ---- Final stage --------------------------------------------------------------
|
||||||
FROM debian:trixie-slim AS final
|
FROM debian:trixie-slim AS final
|
||||||
|
|
||||||
|
|
@ -40,6 +78,39 @@ ARG OPENCODE_SHA256_ARM64=568461b7d4d8c19865c97e9a1102e613049c6039d01fe772154de8
|
||||||
# the pnpm team doesn't recommend Corepack, and Node 25+ dropped bundling it).
|
# the pnpm team doesn't recommend Corepack, and Node 25+ dropped bundling it).
|
||||||
ARG PNPM_VERSION=12.6.0
|
ARG PNPM_VERSION=12.6.0
|
||||||
|
|
||||||
|
# gopls version, built from source at image-build time against the pinned Go
|
||||||
|
# toolchain (FROM golang:... above) via `go install`. Go's module system
|
||||||
|
# verifies this against the public checksum database (sum.golang.org)
|
||||||
|
# automatically, so no separate hash-pinning step is needed here.
|
||||||
|
ARG GOPLS_VERSION=0.23.0
|
||||||
|
|
||||||
|
# typescript + typescript-language-server versions, installed as global npm
|
||||||
|
# packages. Pinned to typescript's LAST JavaScript-based release (6.0.x) on
|
||||||
|
# purpose, NOT "latest" (7.x): TypeScript 7 is a native Go rewrite that no
|
||||||
|
# longer ships tsserver.js, which both typescript-language-server and
|
||||||
|
# OpenCode's own LSP client (which resolves "typescript/lib/tsserver.js"
|
||||||
|
# directly) require. Re-evaluate this pin if typescript-language-server ever
|
||||||
|
# ships a tsgo-native mode.
|
||||||
|
ARG TYPESCRIPT_VERSION=6.0.3
|
||||||
|
ARG TS_LS_VERSION=6.0.1
|
||||||
|
|
||||||
|
# jdtls: NOT distributed via GitHub Releases -- real distribution is
|
||||||
|
# Eclipse's own download server. Architecture-independent (pure JVM). Hash
|
||||||
|
# hand-verified against Eclipse's own published .sha256 file at
|
||||||
|
# https://download.eclipse.org/jdtls/milestones/<version>/<asset>.sha256 --
|
||||||
|
# re-run that check whenever JDTLS_VERSION/JDTLS_BUILD are bumped.
|
||||||
|
ARG JDTLS_VERSION=1.61.0
|
||||||
|
ARG JDTLS_BUILD=202609031315
|
||||||
|
ARG JDTLS_SHA256=338e7e73d61836651ba2453919a0d34fa763eb4e7c03342092309bffb8934c64
|
||||||
|
|
||||||
|
# kotlin-lsp: JetBrains' official server (github.com/Kotlin/kotlin-lsp), not
|
||||||
|
# the stale, long-unmaintained fwcd/kotlin-language-server. Per-arch native
|
||||||
|
# binary; JetBrains publishes no checksum, so these are hand-computed from
|
||||||
|
# the downloaded assets themselves, same as OPENCODE_SHA256_* above.
|
||||||
|
ARG KOTLIN_LSP_VERSION=263.4702.0
|
||||||
|
ARG KOTLIN_LSP_SHA256_AMD64=1e11d2e5fefbf9ea215ad8dd6be95f2222897cd086e8cb7a661a52084a590405
|
||||||
|
ARG KOTLIN_LSP_SHA256_ARM64=ec7cb254a6662a07fff9f10e4365226afab6c40008f8a974c10ac5e785d6510f
|
||||||
|
|
||||||
# ca-certificates : TLS roots for curl/git/npm/pnpm/JVM.
|
# ca-certificates : TLS roots for curl/git/npm/pnpm/JVM.
|
||||||
# fontconfig,
|
# fontconfig,
|
||||||
# libfreetype6 : Temurin's font subsystem needs these even headless.
|
# libfreetype6 : Temurin's font subsystem needs these even headless.
|
||||||
|
|
@ -60,16 +131,38 @@ RUN apt-get update && \
|
||||||
openssh-client && \
|
openssh-client && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
# --- JDK / Node, copied from the source stages ---------------------------------
|
# --- JDK / Node / Go / Rust, copied from the source stages ---------------------
|
||||||
COPY --from=jdk-source /opt/java/openjdk /opt/java/openjdk
|
COPY --from=jdk-source /opt/java/openjdk /opt/java/openjdk
|
||||||
COPY --from=node-source /usr/local/bin /usr/local/bin
|
COPY --from=node-source /usr/local/bin /usr/local/bin
|
||||||
COPY --from=node-source /usr/local/lib/node_modules /usr/local/lib/node_modules
|
COPY --from=node-source /usr/local/lib/node_modules /usr/local/lib/node_modules
|
||||||
|
COPY --from=go-source /usr/local/go /usr/local/go
|
||||||
|
COPY --from=rust-source /usr/local/cargo /usr/local/cargo
|
||||||
|
COPY --from=rust-source /usr/local/rustup /usr/local/rustup
|
||||||
|
|
||||||
# /usr/local/bin is already on Debian's default PATH, so node/npm/npx need no
|
# /usr/local/bin is already on Debian's default PATH, so node/npm/npx need no
|
||||||
# extra PATH entry. JAVA_HOME/bin and PNPM_HOME are non-standard and need one.
|
# extra PATH entry. Everything else here (JDK, pnpm, Go, Rust) lives under a
|
||||||
|
# non-standard prefix and needs one.
|
||||||
ENV JAVA_HOME=/opt/java/openjdk
|
ENV JAVA_HOME=/opt/java/openjdk
|
||||||
ENV PNPM_HOME=/opt/pnpm
|
ENV PNPM_HOME=/opt/pnpm
|
||||||
ENV PATH="${JAVA_HOME}/bin:${PNPM_HOME}/bin:${PATH}"
|
# GOPATH: writable install/cache dir for `go install` -- both the build-time
|
||||||
|
# gopls install below and anything `go`/gopls itself does at runtime (e.g.
|
||||||
|
# module downloads while analyzing a mounted project). Made world-writable
|
||||||
|
# further down, for the same --userns=keep-id reason /home/dev is.
|
||||||
|
ENV GOPATH=/go
|
||||||
|
ENV GOROOT=/usr/local/go
|
||||||
|
# CARGO_HOME/RUSTUP_HOME: matches the layout already baked into the
|
||||||
|
# rust-source image, so the copied toolchain and rustup metadata (including
|
||||||
|
# the recorded default toolchain) keep working unmodified.
|
||||||
|
ENV CARGO_HOME=/usr/local/cargo
|
||||||
|
ENV RUSTUP_HOME=/usr/local/rustup
|
||||||
|
ENV PATH="${JAVA_HOME}/bin:${PNPM_HOME}/bin:${GOROOT}/bin:${GOPATH}/bin:${CARGO_HOME}/bin:${PATH}"
|
||||||
|
# Makes the global `typescript` package (installed below) resolvable via
|
||||||
|
# Node's module resolution from *any* project directory OpenCode mounts at
|
||||||
|
# /workspace, even ones with no local node_modules of their own -- needed
|
||||||
|
# because OpenCode's TypeScript LSP support resolves
|
||||||
|
# "typescript/lib/tsserver.js" relative to the project directory, and
|
||||||
|
# NODE_PATH is the fallback once that climb reaches the filesystem root.
|
||||||
|
ENV NODE_PATH=/usr/local/lib/node_modules
|
||||||
|
|
||||||
# Fixed HOME: the container is run with --userns=keep-id, so the runtime UID
|
# Fixed HOME: the container is run with --userns=keep-id, so the runtime UID
|
||||||
# is whatever host user invoked `podman run`, which has no /etc/passwd entry
|
# is whatever host user invoked `podman run`, which has no /etc/passwd entry
|
||||||
|
|
@ -81,6 +174,9 @@ ENV HOME=/home/dev
|
||||||
# OPENCODE_CONFIG_DIR is OpenCode's one confirmed config-location override.
|
# OPENCODE_CONFIG_DIR is OpenCode's one confirmed config-location override.
|
||||||
ENV OPENCODE_CONFIG_DIR=/home/dev/.config/opencode
|
ENV OPENCODE_CONFIG_DIR=/home/dev/.config/opencode
|
||||||
RUN mkdir -p /home/dev && chmod 1777 /home/dev
|
RUN mkdir -p /home/dev && chmod 1777 /home/dev
|
||||||
|
# GOPATH needs to be writable by any --userns=keep-id-mapped UID too, for the
|
||||||
|
# same reason /home/dev is (see above).
|
||||||
|
RUN mkdir -p /go && chmod 1777 /go
|
||||||
|
|
||||||
# pnpm: standalone installer, pinned version. SHELL must be set explicitly --
|
# pnpm: standalone installer, pinned version. SHELL must be set explicitly --
|
||||||
# the installer can't infer a shell type inside a minimal `RUN` environment
|
# the installer can't infer a shell type inside a minimal `RUN` environment
|
||||||
|
|
@ -88,6 +184,58 @@ RUN mkdir -p /home/dev && chmod 1777 /home/dev
|
||||||
RUN curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION="${PNPM_VERSION}" SHELL=/bin/bash sh - && \
|
RUN curl -fsSL https://get.pnpm.io/install.sh | env PNPM_VERSION="${PNPM_VERSION}" SHELL=/bin/bash sh - && \
|
||||||
chmod -R a+rX "${PNPM_HOME}"
|
chmod -R a+rX "${PNPM_HOME}"
|
||||||
|
|
||||||
|
# rust-analyzer: installed as a rustup component, same trust chain (signed,
|
||||||
|
# checksum-verified by rustup itself) as the rest of the copied Rust
|
||||||
|
# toolchain. Unlike gopls below, OpenCode has no auto-download fallback for
|
||||||
|
# rust-analyzer -- it must already be resolvable on PATH.
|
||||||
|
RUN rustup component add rust-analyzer
|
||||||
|
|
||||||
|
# gopls: built from source via `go install`, pinned to GOPLS_VERSION (see the
|
||||||
|
# ARG comment above for why this needs no separate hash-pinning step).
|
||||||
|
RUN go install golang.org/x/tools/gopls@v${GOPLS_VERSION} && \
|
||||||
|
chmod -R a+rwX "${GOPATH}"
|
||||||
|
|
||||||
|
# typescript + typescript-language-server: global npm install, pinned (see
|
||||||
|
# the ARG comment above for why TYPESCRIPT_VERSION deliberately isn't "latest").
|
||||||
|
RUN npm install -g \
|
||||||
|
"typescript@${TYPESCRIPT_VERSION}" \
|
||||||
|
"typescript-language-server@${TS_LS_VERSION}"
|
||||||
|
|
||||||
|
# jdtls: architecture-independent (pure JVM) tarball, fetched directly from
|
||||||
|
# Eclipse's own download server (not GitHub Releases). No bin/jdtls launcher
|
||||||
|
# ships in it -- scripts/jdtls (copied in below) is the hand-written wrapper.
|
||||||
|
RUN set -eu; \
|
||||||
|
curl -fsSL -o /tmp/jdtls.tar.gz \
|
||||||
|
"https://download.eclipse.org/jdtls/milestones/${JDTLS_VERSION}/jdt-language-server-${JDTLS_VERSION}-${JDTLS_BUILD}.tar.gz"; \
|
||||||
|
printf '%s /tmp/jdtls.tar.gz\n' "$JDTLS_SHA256" | sha256sum -c -; \
|
||||||
|
mkdir -p /opt/jdtls; \
|
||||||
|
tar -xzf /tmp/jdtls.tar.gz -C /opt/jdtls; \
|
||||||
|
rm -f /tmp/jdtls.tar.gz
|
||||||
|
COPY scripts/jdtls /usr/local/bin/jdtls
|
||||||
|
RUN chmod +x /usr/local/bin/jdtls
|
||||||
|
|
||||||
|
# kotlin-lsp: arch-aware fetch (same pattern as the OpenCode section below),
|
||||||
|
# SHA256 verified by hand (see the ARG comment above). The tarball extracts
|
||||||
|
# to a versioned top-level dir, flattened here via --strip-components=1.
|
||||||
|
# bin/intellij-server is the real binary -- kotlin-lsp.sh (not copied) is
|
||||||
|
# just a deprecated wrapper that execs it with no extra flags, confirmed by
|
||||||
|
# reading that script directly. Symlinked under both plausible command names
|
||||||
|
# since it's unconfirmed which one OpenCode's Kotlin LSP integration expects.
|
||||||
|
RUN set -eu; \
|
||||||
|
case "$TARGETARCH" in \
|
||||||
|
amd64) KLS_ASSET="kotlin-server-${KOTLIN_LSP_VERSION}.tar.gz"; KLS_SHA256="$KOTLIN_LSP_SHA256_AMD64" ;; \
|
||||||
|
arm64) KLS_ASSET="kotlin-server-${KOTLIN_LSP_VERSION}-aarch64.tar.gz"; KLS_SHA256="$KOTLIN_LSP_SHA256_ARM64" ;; \
|
||||||
|
*) echo "ERROR: unsupported TARGETARCH='$TARGETARCH'" >&2; exit 1 ;; \
|
||||||
|
esac; \
|
||||||
|
curl -fsSL -o /tmp/kotlin-lsp.tar.gz \
|
||||||
|
"https://download.jetbrains.com/language-server/kotlin-server/${KOTLIN_LSP_VERSION}/${KLS_ASSET}"; \
|
||||||
|
printf '%s /tmp/kotlin-lsp.tar.gz\n' "$KLS_SHA256" | sha256sum -c -; \
|
||||||
|
mkdir -p /opt/kotlin-lsp; \
|
||||||
|
tar -xzf /tmp/kotlin-lsp.tar.gz -C /opt/kotlin-lsp --strip-components=1; \
|
||||||
|
rm -f /tmp/kotlin-lsp.tar.gz; \
|
||||||
|
ln -s /opt/kotlin-lsp/bin/intellij-server /usr/local/bin/kotlin-lsp; \
|
||||||
|
ln -s /opt/kotlin-lsp/bin/intellij-server /usr/local/bin/kotlin-language-server
|
||||||
|
|
||||||
# OpenCode: arch-aware fetch, SHA256 verification, install.
|
# OpenCode: arch-aware fetch, SHA256 verification, install.
|
||||||
# Asset naming uses "x64" for the amd64 arch, not "amd64".
|
# Asset naming uses "x64" for the amd64 arch, not "amd64".
|
||||||
# Confirmed layout: both tarballs contain the binary flat at top level as
|
# Confirmed layout: both tarballs contain the binary flat at top level as
|
||||||
|
|
@ -113,7 +261,14 @@ RUN { ldd /usr/local/bin/opencode || true; } | tee /tmp/opencode-ldd.txt && \
|
||||||
exit 1; \
|
exit 1; \
|
||||||
fi && \
|
fi && \
|
||||||
rm -f /tmp/opencode-ldd.txt
|
rm -f /tmp/opencode-ldd.txt
|
||||||
RUN java -version && node --version && pnpm --version && git --version && curl --version
|
# jdtls/kotlin-lsp aren't invoked here (both block waiting on stdio LSP
|
||||||
|
# input with no --version-style flag) -- just checked for presence instead.
|
||||||
|
RUN java -version && node --version && pnpm --version && git --version && curl --version && \
|
||||||
|
go version && rustc --version && rust-analyzer --version && gopls version && \
|
||||||
|
tsc --version && typescript-language-server --version && \
|
||||||
|
test -x /usr/local/bin/jdtls && \
|
||||||
|
ls /opt/jdtls/plugins/org.eclipse.equinox.launcher_*.jar >/dev/null && \
|
||||||
|
test -x /usr/local/bin/kotlin-lsp && test -x /opt/kotlin-lsp/bin/intellij-server
|
||||||
|
|
||||||
WORKDIR /workspace
|
WORKDIR /workspace
|
||||||
CMD ["opencode"]
|
CMD ["opencode"]
|
||||||
|
|
|
||||||
17
README.md
17
README.md
|
|
@ -5,7 +5,8 @@ A rootless Podman container for running [OpenCode](https://github.com/anomalyco/
|
||||||
## What this gives you
|
## What this gives you
|
||||||
|
|
||||||
- A hash-pinned, integrity-verified build of OpenCode (not "latest" — an exact version, checked against a SHA256 captured at build time).
|
- A hash-pinned, integrity-verified build of OpenCode (not "latest" — an exact version, checked against a SHA256 captured at build time).
|
||||||
- JDK 25 (LTS), Node 24 (LTS), pnpm, git, curl, openssh-client.
|
- JDK 25 (LTS), Node 24 (LTS), Go, Rust, pnpm, git, curl, openssh-client.
|
||||||
|
- Language servers for Go, Rust, TypeScript/JavaScript, Java, and Kotlin, ready for OpenCode's built-in LSP client (see [LSP support](#lsp-support) below).
|
||||||
- The current directory mounted read-write as `/workspace`.
|
- The current directory mounted read-write as `/workspace`.
|
||||||
- OpenCode's config, data, and session state shared across every workdir/container, so logging in once carries over everywhere.
|
- OpenCode's config, data, and session state shared across every workdir/container, so logging in once carries over everywhere.
|
||||||
- Every container joined to a shared Podman network so it can reach other dev containers by name.
|
- Every container joined to a shared Podman network so it can reach other dev containers by name.
|
||||||
|
|
@ -50,6 +51,20 @@ The edit is wrapped in `# >>> opencode-sandbox >>>` markers so re-running
|
||||||
`make install` never duplicates it, and is skipped entirely if
|
`make install` never duplicates it, and is skipped entirely if
|
||||||
`~/.local/bin` is already on `PATH`.
|
`~/.local/bin` is already on `PATH`.
|
||||||
|
|
||||||
|
## LSP support
|
||||||
|
|
||||||
|
OpenCode's built-in LSP client is off by default — turn it on per-project with `"lsp": true` in that project's `opencode.json` (or configure individual servers there; see OpenCode's own docs for the object form). Once enabled, this image is ready for it:
|
||||||
|
|
||||||
|
| Language | Server | How it gets there |
|
||||||
|
|---|---|---|
|
||||||
|
| Go | `gopls` | Built from source at image-build time (`go install`), pinned via `GOPLS_VERSION` in the Containerfile. |
|
||||||
|
| Rust | `rust-analyzer` | Installed as a `rustup` component at image-build time — OpenCode has no auto-download fallback for this one, so it has to already be on `PATH`. |
|
||||||
|
| TypeScript / JavaScript | `typescript` + `typescript-language-server` | Installed as global npm packages, pinned via `TYPESCRIPT_VERSION`/`TS_LS_VERSION`. Pinned to TypeScript's last JavaScript-based release (6.0.x) — TypeScript 7 is a native Go rewrite that dropped `tsserver.js`, which `typescript-language-server` needs to attach to. `NODE_PATH` is set so the global `typescript` package resolves even from a project with no local `node_modules`. |
|
||||||
|
| Java | `jdtls` | Pre-baked — OpenCode has no auto-download fallback for Java at all, so this has to be on `PATH`. Fetched straight from Eclipse's own download server (not GitHub Releases; architecture-independent, pure JVM). No `bin/jdtls` ships upstream, so `scripts/jdtls` is a hand-written launcher wrapper — the same convention every other jdtls consumer (nvim-jdtls, mason.nvim, coc-java) uses — which also manages a persistent, per-project `-data` workspace dir under OpenCode's host-persisted data dir. |
|
||||||
|
| Kotlin | `kotlin-lsp` | Pre-baked — JetBrains' official server (`github.com/Kotlin/kotlin-lsp`), fetched per-arch and hash-verified by hand (JetBrains publishes no checksum). Ships its own bundled JetBrains Runtime, so it needs none of this image's JDK. Symlinked as both `kotlin-lsp` and `kotlin-language-server`, since it's unconfirmed which name OpenCode's Kotlin integration expects. |
|
||||||
|
|
||||||
|
Bumping a pinned LSP version means editing the corresponding `ARG`/`FROM` tag in the Containerfile and rebuilding (`make build`).
|
||||||
|
|
||||||
## How it's put together
|
## How it's put together
|
||||||
|
|
||||||
**Containerfile** — multi-stage build on `debian:trixie-slim`:
|
**Containerfile** — multi-stage build on `debian:trixie-slim`:
|
||||||
|
|
|
||||||
39
scripts/jdtls
Executable file
39
scripts/jdtls
Executable file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# jdtls launcher: the eclipse.jdt.ls project ships no bin/jdtls of its own --
|
||||||
|
# every consumer (nvim-jdtls, mason.nvim, coc-java, etc.) hand-writes one, so
|
||||||
|
# this mirrors that same well-established convention. Installed at
|
||||||
|
# /usr/local/bin/jdtls by the Containerfile so OpenCode's Java LSP
|
||||||
|
# integration (which has no auto-download fallback for jdtls, unlike gopls)
|
||||||
|
# can find a bare `jdtls` command on PATH.
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
JDTLS_HOME=/opt/jdtls
|
||||||
|
|
||||||
|
# jdtls requires a persistent, project-specific workspace dir (`-data`): the
|
||||||
|
# same one must be reused across restarts for a given project, and different
|
||||||
|
# projects must NOT share one (jdtls indexes it as if it were a single
|
||||||
|
# workspace). Derived from a hash of the real project path and stored under
|
||||||
|
# OpenCode's own host-persisted data dir (see the Makefile's DATA_DIR bind
|
||||||
|
# mount) so it survives container restarts instead of vanishing with `--rm`.
|
||||||
|
workspace_hash=$(printf '%s' "$(pwd -P)" | cksum | cut -d' ' -f1)
|
||||||
|
data_dir="$HOME/.local/share/opencode/jdtls-workspaces/$workspace_hash"
|
||||||
|
mkdir -p "$data_dir"
|
||||||
|
|
||||||
|
launcher=$(ls "$JDTLS_HOME"/plugins/org.eclipse.equinox.launcher_*.jar 2>/dev/null | head -n1)
|
||||||
|
if [ -z "$launcher" ]; then
|
||||||
|
echo "jdtls: equinox launcher jar not found under $JDTLS_HOME/plugins" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec java \
|
||||||
|
--add-modules=ALL-SYSTEM \
|
||||||
|
--add-opens java.base/java.util=ALL-UNNAMED \
|
||||||
|
--add-opens java.base/java.lang=ALL-UNNAMED \
|
||||||
|
-Declipse.application=org.eclipse.jdt.ls.core.id1 \
|
||||||
|
-Dosgi.bundles.defaultStartLevel=4 \
|
||||||
|
-Declipse.product=org.eclipse.jdt.ls.core.product \
|
||||||
|
-Dlog.protocol=true -Dlog.level=ALL -Xmx1G \
|
||||||
|
-jar "$launcher" \
|
||||||
|
-configuration "$JDTLS_HOME/config_linux" \
|
||||||
|
-data "$data_dir" \
|
||||||
|
"$@"
|
||||||
Reference in a new issue