mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 08:07:49 +00:00
Full debug info made up most of target/: each worktree's build output was 15–30 GB. Dev builds now keep line tables for workspace crates (file:line stays in backtraces) and no debug info for dependencies, which brings a cold `cargo build` to about 9 GB and roughly halves cold build time. A debugger can't show locals any more; re-enable with `--config profile.dev.debug=true` when needed. Co-authored-by: LittleGuava <52166187+LittleGuava@users.noreply.github.com>
130 lines
7.7 KiB
Markdown
130 lines
7.7 KiB
Markdown
# OpenIDEA — contributor guide
|
||
|
||
Rust + Tauri 2 desktop IDE with full-featured, multi-language code intelligence.
|
||
Visual style: dark, low-contrast greys, one cool accent
|
||
(`src/styles/tokens.css` is the source of truth for colours and metrics).
|
||
|
||
## Layout
|
||
|
||
- `crates/ide-*` — backend crates; one domain each. Depend on `ide-core` for shared
|
||
types; never reach into another crate's internals.
|
||
- `src-tauri/` — glue only: `state.rs` (AppState / Project), `commands/<domain>.rs`
|
||
(thin typed IPC adapters), `events.rs`. No domain logic here.
|
||
- `src/bindings.ts` — generated by tauri-specta (`pnpm gen:bindings`). Never edit.
|
||
- `src/platform/` — ipc (`call`, `onIdeEvent`, `nextRequestId`), actions registry,
|
||
keymap + dispatcher, context keys / `when` clauses, project store.
|
||
- `src/workbench/contributions.ts` — extension points (tool windows, status items,
|
||
overlays, editor kinds) and cross-feature services (editor, tool windows, notifications).
|
||
- `src/ui/` — design-system primitives. `src/features/<name>/` — one feature each,
|
||
exporting `activate()` registered in `src/features/index.ts`.
|
||
- `languages/<id>.toml` — language definitions (detection, comments, LSP, DAP).
|
||
- `crates/ide-host` — the `openidea-server` binary for remote development and the
|
||
`openidea-plugin` CLI (plugin starter templates live in its `templates.rs`).
|
||
- `wit/` — plugin interface definitions; `plugins/` — sample and bundled plugins.
|
||
Plugin docs: `plugins/README.md`, `docs/plugins/themes.md`.
|
||
- `java/` — JDT LS extension bundles (`java-usages`, `kotlin-bridge`) and the patched
|
||
Lombok agent, embedded into the app by `ide-sdk` / `ide-tools`.
|
||
- `e2e/` — Playwright UI tests (`pnpm e2e`). `fixtures/` — sample projects per language
|
||
for manual and automated testing.
|
||
|
||
## Rules
|
||
|
||
- IPC coordinates: 0-based lines, **UTF-16** columns/offsets everywhere (`ide-core::text`).
|
||
- Every command returns `IdeResult<T>`; convert internal errors at the crate edge.
|
||
- Streaming → `tauri::ipc::Channel<T>`; cancellable → UI-allocated `RequestId` +
|
||
`cancel_request`. Backend → UI notifications → `IdeEvent` via `EventSink`.
|
||
- Long work never blocks the UI thread or a Tauri command thread: use
|
||
`spawn_blocking`/rayon, honour `CancellationToken`.
|
||
- Frontend features never import each other; communicate via actions, contributions
|
||
and services. All user-invocable behaviour is an action with a stable id; default
|
||
shortcuts live in `src/platform/keymaps/`.
|
||
- Styling: CSS Modules + tokens only (no hex literals in components). Inline SVG
|
||
icons from `src/ui/icons.tsx`, never emoji. Real `<button>`/`<input>`; `aria-label` on icon buttons.
|
||
- User-visible text goes through the text catalog: add every new string to both
|
||
`src/platform/locales/text/en.json` and `zh.json` (`textCatalog.test.ts` enforces it).
|
||
Other locales may lack entries; their UI shows the English text until a translator adds it.
|
||
- Keep comments sparse and purposeful; match surrounding style.
|
||
- For GUI verification, prefer Tauri MCP; use Computer Use only when Tauri MCP is
|
||
unavailable or cannot cover the required checks.
|
||
|
||
## Issues & PRs
|
||
|
||
Follow `CONTRIBUTING.md` and `.github/pull_request_template.md`: one problem per PR
|
||
(`Closes #<n>` when it resolves an issue), reproduce first, keep the diff focused, short plain description, and a
|
||
**How it was verified** section with commands run, results and (for UI) before/after screenshots.
|
||
Unclear product decisions → `needs-decision` and stop.
|
||
|
||
## Skills
|
||
|
||
Shared agent skills live in `.agents/skills/` (`.claude/skills/` links to them):
|
||
`verify` drives the running app through Tauri MCP and captures screenshot evidence;
|
||
`issue-fix` takes an issue from reproduction to one PR.
|
||
|
||
## Commands
|
||
|
||
- `pnpm tauri dev` — run the app with worktree isolation (Node 22.18+).
|
||
`pnpm dev:app` also enables the global Tauri API. `pnpm dev:status` reports
|
||
this worktree's running MCP bridges and actual ports.
|
||
- `pnpm build` — typecheck + bundle frontend.
|
||
- `cargo nextest run --workspace` (or `cargo test`), `cargo clippy --workspace --all-targets -- -D warnings`, `cargo fmt --all`.
|
||
- `cargo test -p ide-host --test language_smoke -- --ignored --exact <language>` — code intelligence
|
||
on `fixtures/` with that language's real server installed (CI: `Language smoke`, pinned versions).
|
||
- `pnpm smoke smoke/run.test.ts -t <language>` — run and test that language's fixture through the
|
||
run store and a real `openidea-server` (build it first: `cargo build -p ide-host --bin openidea-server`).
|
||
- `pnpm smoke smoke/debug.test.ts -t <language>` — debug that fixture's entry point the same way, with
|
||
the debugger the IDE installs (on macOS, CodeLLDB and Delve may need Developer Mode:
|
||
`sudo DevToolsSecurity -enable`).
|
||
- `pnpm test`, `pnpm e2e`, `pnpm lint`, `pnpm format:check`, `pnpm knip`, `pnpm typecheck`,
|
||
`pnpm gen:bindings`.
|
||
- `pnpm perf` (UI interaction latency / frames / leaks), `pnpm perf:rust` (criterion
|
||
benches vs budgets). Budgets: `perf/budgets.json`.
|
||
|
||
## Before opening a PR
|
||
|
||
Run what CI runs for the parts you touched:
|
||
|
||
- Rust: `cargo fmt --all --check`, `cargo clippy --workspace --all-targets -- -D warnings`,
|
||
`cargo nextest run --workspace`. After changing IPC types, run `pnpm gen:bindings` and
|
||
commit `src/bindings.ts`; CI fails if it differs.
|
||
- Frontend: `pnpm typecheck`, `pnpm lint`, `pnpm format:check`, `pnpm knip`, `pnpm test`,
|
||
`pnpm build`, and `pnpm e2e` for UI flows.
|
||
- UI or runtime behaviour: verify in the running app (`.agents/skills/verify`).
|
||
|
||
## Pitfalls
|
||
|
||
- Run a subset of frontend tests with `pnpm vitest run <path>`. `pnpm test -- <path>` ignores
|
||
the filter and runs the whole suite, which takes several minutes.
|
||
- Don't run clippy while iterating: `pnpm tauri dev` compiles anyway. Run
|
||
`cargo fmt --all` + `cargo clippy -p <crate> --all-targets -- -D warnings` once, right
|
||
before committing. A cold build cache can take around 5 minutes. Run long checks one at
|
||
a time, not chained in one shell call that may hit the 10-minute tool timeout.
|
||
- `pnpm tauri dev` does a full debug build. Clippy only checks the code, so a passing clippy
|
||
doesn't make the first launch fast.
|
||
|
||
## Parallel worktrees
|
||
|
||
Several worktrees can be developed and run side by side.
|
||
|
||
- Create one per task: `git worktree add ../<name> -b <branch> origin/main`, then
|
||
`pnpm install` in it.
|
||
- Launch with `pnpm tauri dev` / `pnpm dev:app`, not the raw `pnpm exec tauri dev` CLI. The
|
||
wrapper starts Vite on a worktree-derived port (advancing if occupied), passes its actual
|
||
URL to Tauri, and reports an existing launcher instead of starting another for the same
|
||
worktree. HMR uses the Vite port.
|
||
- Debug app identity, data, settings, logs and single-instance scope follow the canonical
|
||
worktree path captured at build time, independent of launch cwd. Launching the same debug
|
||
binary again focuses its existing instance and forwards its path argument. Different
|
||
worktrees and the installed release can coexist. `--release` uses normal release identity
|
||
and bypasses the development wrapper.
|
||
- MCP bridge ports are dynamic (9223–9322). Use `pnpm dev:status`, connect to the reported
|
||
port, verify identifier/cwd, and pass `appIdentifier: <port>` explicitly. Do not assume the
|
||
default MCP session belongs to this worktree.
|
||
- Keep each worktree's Cargo output directory separate; do not point `CARGO_TARGET_DIR` or
|
||
`target` symlinks at a shared directory.
|
||
- Each worktree's first build is cold (several minutes) and `cargo build` output takes
|
||
around 9 GB; tests, clippy and incremental builds add more. Avoid running several heavy builds on one machine at the same time.
|
||
- Stop only processes started for the current worktree/session. Never use broad
|
||
process-name kills such as `pkill openidea`.
|
||
- When done: stop that worktree's app and dev session, delete its build output, then
|
||
`git worktree remove ../<name>`.
|