Skip to content

feat(ide): IntelliJ-grade Java in the web IDE — New→Java scaffolding, full JDT.LS IntelliSense, refactoring, Call/Type Hierarchy & performance#6076

Open
iliyan-velichkov wants to merge 22 commits into
masterfrom
feat/web-ide-java-authoring
Open

feat(ide): IntelliJ-grade Java in the web IDE — New→Java scaffolding, full JDT.LS IntelliSense, refactoring, Call/Type Hierarchy & performance#6076
iliyan-velichkov wants to merge 22 commits into
masterfrom
feat/web-ide-java-authoring

Conversation

@iliyan-velichkov

@iliyan-velichkov iliyan-velichkov commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Turns the in-browser Monaco editor into an IntelliJ-grade Java environment: scaffolding new types,
full JDT.LS-backed IntelliSense, refactoring and code generation, Call/Type Hierarchy, and the
warm-up performance work to make it all feel instant.

All Java intelligence is served by a per-workspace JDT Language Server (ide-java-lsp), bridged
to the editor over WebSocket and — for views that live outside the editor iframe — over a small
server-side HTTP facade.

New → Java scaffolding (Projects view)

A dedicated Java context-menu (project & folder) creates, with automatic package-folder creation
and a matching package declaration:

  • Base types: Package, Class, Interface, Enum, Annotation, Record, Exception.
  • Strong-interface skeletons in the org.eclipse.dirigible.sdk.* style: Controller, Job, Listener,
    WebSocket, Repository
    (Repository also prompts for the entity type it manages).

A fully-qualified name creates the folder chain; a simple name lands in the project root. The created
file is opened and revealed/selected in the tree.

Note: the Java entries live in a top-level Java submenu (sibling of New), not nested inside New
— BlimpKit disables menu scrolling for any menu that contains a submenu child, and New must keep
scrolling once enough artefact templates are registered.

Editor IntelliSense (Monaco ⇄ JDT.LS)

Completion with auto-import and SDK-prioritised ordering, first-Ctrl+Space responsiveness,
hover, signature help, document highlight, outline / document symbols, folding, selection
ranges, inlay parameter-name hints, and Java keyword suggestions.

Navigation works across files (the editor holds a single-file model, so cross-file targets are
fetched and opened on demand): Go to Definition, Find References (with code preview), Go to
Implementations
, Go to Type Definition.

Refactoring & code generation

  • Cross-file rename (F2): updates every reference across the workspace and, when a public type is
    renamed, renames the type's own .java file; the Projects tree updates in place and the renamed
    file is revealed. Stale-error / old-name-in-completion sync issues fixed.
  • Quick fixes & source actions: generate constructor / toString / getters & setters,
    override/implement methods, implement required interface methods, organize imports.
  • Refactor assists surfaced via the lightbulb / Refactor menu, including create field from a
    constructor parameter
    and extract refactorings.
  • Surround With / Refactor… action (Cmd/Ctrl+Alt+T).

Formatting, imports & completion polish

  • Format on save and organize-imports on save (gated by the auto-format toggle).
  • Postfix completion (expr.var, .for, .fori, .sout, .null, …).
  • Completion result count capped for snappier popups.

Semantic highlighting

Real JDT.LS semantic tokens with explicit colour rules for the full legend in blimpkit-dark,
classic-dark, and a new blimpkit-light theme. Keyword/modifier tokens are mapped explicitly so
keywords don't blank out under the semantic layer (palettes mirror VS Code dark+/light+).

Call & Type Hierarchy (new bottom panel)

view-java-hierarchy plus editor actions Show Call Hierarchy (Ctrl+Alt+H) and Show Type
Hierarchy
(Ctrl+H). The panel resolves the root and lazily expands each node — call → Callers /
Callees, type → Supertypes / Subtypes (toolbar toggle); clicking a node navigates to its declaration.

Backed by a new server facade JavaLspQueryEndpoint (/services/ide/java-lsp) that drives the
shared JDT.LS instance for these non-editor views. The corresponding callHierarchy/typeHierarchy
capabilities are advertised in both the server-side and editor-client initialize, so they
survive whichever side last (re)initializes the shared process. (URIs travel as the browser's virtual
file:///workspace/<ws>/… form and are bridge-translated to/from real paths.)

Performance

  • JDT.LS index is persisted across restarts behind a classpath fingerprint — no full re-index on
    every boot; rebuilt only when the platform classpath actually changes.
  • Classpath is pre-warmed at startup so the first Java file opened doesn't pay extraction.
  • Configurable JDT.LS heap via DIRIGIBLE_JAVA_LSP_MAX_HEAP (default 2g).
  • Reduced LSP chatter: code-action triggerKind plumbed through; references/implementations CodeLens
    kept off by default.

Tests & CI

  • CreateJavaArtifactsIT drives the New → Java menu and asserts each artefact's location and content
    over the workspace REST API; test framework gains a cascading-menu click helper.
  • CodeQL: exclude the generated java-lsp-client.js bundle (esbuild output embedding vendored
    vscode-languageserver types — the .ts source is still analysed); 4 java/log-injection alerts
    dismissed as false positives (the logged username/workspace already pass through sanitize() which
    strips \r\n\t).

Notes

  • Several LSP behaviours are index/timing dependent; final confirmation is a manual retest on a warm
    project.
  • UI module resources are bundled into the fat jar — a running instance must be rebuilt and restarted
    to pick up editor/view changes.
  • No run/debug gutter icons (intentionally out of scope).

🤖 Generated with Claude Code

iliyan-velichkov and others added 2 commits June 23, 2026 11:36
…ull Monaco Java IntelliSense

Make writing client Java in the browser IDE feel like IntelliJ.

New → Java submenu (Projects view):
- Package (creates the nested folder chain from a dotted name)
- Class, Interface, Enum, Annotation, Record, Exception
- Controller, Job, Listener, WebSocket, Repository — strong-interface skeletons
A fully-qualified name (com.test.MyClass) creates the package folders and the
matching package declaration; a simple name lands in the selected folder. Logic
lives in a new pure helper js/java-new.js; projects.js orchestrates dialog →
nested folder → file → open via the existing WorkspaceService.

Java IntelliSense (editor-monaco LSP client):
- Auto-import on completion (completionItem/resolve → additionalTextEdits)
- Dirigible SDK suggestions ranked first (sortText bucketing)
- Code actions: quick-fixes, organize imports, and generate
  constructor/getters/setters/toString/equals&hashCode with a member-picker dialog
- Rename symbol, find references, document formatting
- Server→client workspace/applyEdit + configuration handling
- Format-on-save for Java reuses the existing TypeScript auto-format mechanism via
  the new formatting provider (same global toggle)

Tests:
- CreateJavaArtifactsIT drives New → Java end to end and asserts folders, files,
  package declarations and skeleton signals over the workspace REST API
- Browser.hoverOnElementByAttributePatternAndText + Workbench.createJavaArtifact

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…avaArtifactsIT pass

JDT.LS was launched with -Xmx512m, which OOMs ("Java heap space") while indexing
the full platform classpath (~1000+ entries), killing the language server and with
it completion / auto-import / code actions. Make the max heap configurable via
DIRIGIBLE_JAVA_LSP_MAX_HEAP (DirigibleConfig.JAVA_LSP_MAX_HEAP) and default it to 2g.

Test framework: CreateJavaArtifactsIT now drives the nested New → Java → <item>
context menu reliably. Replaced the strict hover/visibility approach (which cannot
reach a collapsed 3rd-level submenu in headless Chrome, where moveToElement does not
fire mouseenter) with Browser.clickCascadingMenuItem, which scopes to the open
context menu and drives its own Angular mouseenter/click handlers in a single
in-frame script. Verified: the IT passes end to end (package folders, package
declarations and strong-interface skeleton signals all asserted over the workspace
REST API).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@iliyan-velichkov

Copy link
Copy Markdown
Contributor Author

Follow-up while testing locally

JDT.LS heap fix. JDT.LS launched with -Xmx512m, which throws OutOfMemoryError: Java heap space while indexing the full platform classpath (~1000+ entries), killing the language server (and with it completion / auto-import / code actions). Max heap is now configurable via DIRIGIBLE_JAVA_LSP_MAX_HEAP (DirigibleConfig.JAVA_LSP_MAX_HEAP), default 2g. (commit 880a01b)

Integration test now green. CreateJavaArtifactsIT passes end to end. Reaching the nested New → Java → <item> menu needed a headless-robust navigator — Browser.clickCascadingMenuItem scopes to the open context menu and drives its own Angular mouseenter/click handlers in one in-frame script (a strict hover/visibility approach can't reach a collapsed 3rd-level submenu headless: moveToElement doesn't fire mouseenter, and per-step frame switches collapse the menu).

iliyan-velichkov and others added 12 commits June 23, 2026 13:42
…ntity is an input

- After creating a Java artefact the project tree now expands to and selects the new
  file (building/reusing the package folder nodes) instead of reloading the project
  node, which collapsed the structure.
- The Repository skeleton no longer reuses the repository class name as its entity
  type parameter (DemoRepo → JavaRepository<DemoRepo>). The dialog now prompts for the
  entity type (simple or fully-qualified; a qualified name adds the import), producing
  e.g. JavaRepository<Country> with super(Country.class).
- CreateJavaArtifactsIT + Workbench.createJavaArtifact updated for the entity prompt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…mpletion

- Completion now propagates JDT.LS's isIncomplete so Monaco re-queries as you type
  (fixes the first Ctrl+Space showing nothing), and forwards the real trigger
  kind/character plus filterText/preselect/commitCharacters for correct filtering.
- Registered a Monaco editor opener: Go to Definition / Find References to a symbol
  in another workspace file now opens that file in the IDE and reveals the line
  (the single-file editor previously had no model for other files, so navigation
  silently did nothing). Same-file targets still jump within the editor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… file

Renaming a Java symbol (F2) now applies JDT.LS's full rename WorkspaceEdit across the
whole workspace instead of only the current file:

- Text edits in every referencing file are applied and persisted (read-modify-write
  over the workspace REST API, CSRF-guarded); the current file goes through the live
  Monaco model + save.
- RenameFile operations are honoured, so renaming a public class/interface/enum also
  renames its .java file and updates all references; when that file is the one being
  edited, the editor tab switches to the new file.
- Other open editors reload the changed files (dirty editors are skipped to avoid
  clobbering unsaved work) via a new monaco.file.reload topic.

Falls back to current-file-only rename if the IDE persistence hook is unavailable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…s, semantic colors, CodeLens, override/implement, keywords

Adds JDT.LS-backed language features to the Monaco Java editor:

Navigation & structure:
- Outline / breadcrumbs / sticky scroll (documentSymbol), code folding
  (foldingRange), occurrence highlight (documentHighlight), Go to Implementation
  and Go to Type Definition (reusing the cross-file editor opener), Format
  Selection (rangeFormatting) and Smart Expand Selection (selectionRange).

Editor intelligence:
- Inlay hints (parameter names + inferred types) and semantic-token highlighting
  (legend captured from the initialize result; semanticHighlighting enabled on the
  editor).
- CodeLens with "N references / N implementations" (click opens the peek).
- Override/Implement Methods wired into the existing member-picker generate flow.
- Always-available Java keyword completion, ranked below SDK/LSP results.

Advertises the matching client capabilities and enables the JDT.LS inlay-hint and
references/implementations CodeLens settings. All are additive providers; the exact
JDT.LS command ids are guarded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…yword colors

- Find/Peek References (and go-to-definition/implementation/type-definition) now
  create in-memory models for the referenced files, so the peek shows a real code
  preview instead of only file/line/column.
- Flush the pending debounced didChange before a completion request, so JDT.LS sees
  the just-typed text on the first Ctrl+Space (previously the first invocation
  completed against stale content and only the second worked).
- Revert the forced semanticHighlighting flag: JDT.LS emits keyword/modifier
  semantic tokens the vs-dark-based themes don't style, which left Java keywords
  uncolored. The semantic-tokens provider stays registered (inert until a theme opts
  in) so basic Monarch keyword coloring is restored.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e after rename

Root cause of "no quick-fixes / no Implement Methods / Generate toString does nothing":
- We advertised the *PromptSupport extended capabilities, so JDT.LS returned source
  actions (generate toString/constructors/accessors, override/implement, organize
  imports) as client-side "java.action.*Prompt" commands that the vscode-java
  extension implements but we don't — and the server commands we tried to call
  (checkToStringStatus/generateToString/…) don't exist on JDT.LS. Dropping those
  flags makes JDT.LS return the same actions as resolvable WorkspaceEdits (all
  members), which applyCodeAction resolves and applies directly.
- Code-action requests sent diagnostics reconstructed from Monaco markers, which lose
  the LSP code/data JDT.LS matches quick-fixes against. We now keep the original
  published diagnostics per file and send the ones overlapping the request range, so
  "Add unimplemented methods", "Create field", etc. appear.

Also: the Projects view ignored file rename/move events, so after a class rename the
tree still showed the old file. It now reloads on platform.files.renamed/moved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…n completion)

Renaming a public type (F2) had two defects:
- When JDT.LS ordered the RenameFile before the text edit, the edit was keyed by the
  new URI; we wrote the old content (old type name) into the new file, producing
  "The public type X must be defined in its own file". Edits are now re-attributed to
  the on-disk (old) URI before applying, so the new file gets the new type name.
- After renaming on disk we never told JDT.LS, so it kept validating stale state until
  a page refresh and kept suggesting the old type name in completion. We now send
  textDocument/didClose for the renamed-away file and workspace/didChangeWatchedFiles
  (Deleted old / Created new / Changed edited) so the server re-indexes immediately —
  clearing the stale diagnostic and dropping the old name from completion.

This also removes the exception/fallback path that made the first Enter occasionally
apply only the in-editor edit without renaming the file.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Cap JDT.LS completion at maxResults=50 so import/type suggestions over the large
  platform classpath return faster.
- On a Java file rename, the Projects view now renames the matching tree node in place
  and selects it (keeping it revealed) instead of doing a full collapse-reload, so the
  renamed file stays visible and highlighted; falls back to a reload if the node isn't
  loaded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…meter to field)

Set the Monaco code-action lightbulb to "on" so it appears whenever any code action is
available at the cursor — not only on diagnostics. This surfaces JDT.LS refactor
assists like "Assign parameter to new field" / "Assign all parameters to new fields"
(kind refactor.assign.field) on a constructor parameter, plus Extract Method/Variable/
Constant/Field, as a visible suggestion instead of being hidden behind Refactor…. The
assist itself already flowed through the existing code-action provider.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ce CodeLens

The Java editor had become slow to "enable" features on a fresh project and sluggish
while typing. Two avoidable load sources, on top of JDT.LS's inherent cold-start
indexing of the large platform classpath:

- Code-action requests omitted triggerKind, so JDT.LS computed the full set of quick
  assists/refactorings on every passive-lightbulb evaluation (every cursor move). Now
  we forward Monaco's trigger (Invoke=1/Auto=2, 1:1 with the LSP kind): the passive
  lightbulb computes only quick-fixes (cheap); full assists/refactorings only on
  explicit Ctrl+. / Refactor….
- references/implementations CodeLens ran a reference search for every declaration on
  open and on every edit — the heaviest always-on provider. Disabled by default.
- Reverted the eager `lightbulb: 'on'` (its purpose was to surface refactor assists in
  the passive bulb, which we instead keep on the explicit Refactor… surface).

Refactor assists like "Assign parameter to new field" / Extract remain available via
Refactor… (Ctrl+Shift+R).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ling / CreateNewFileIT)

BlimpKit's context menu disables scrolling for any submenu that contains a nested
submenu (contextmenu.js canScroll). Nesting the "Java" group inside "New" therefore
turned off scrolling for the whole New menu, so once enough artefact templates are
registered the menu overflows the viewport and top items (e.g. "JavaScript Service")
become unreachable — which failed CreateNewFileIT.

Move "Java" to a top-level context-menu entry (sibling of New) on project/folder
nodes. New keeps its scrolling; "Java" is its own 2-level submenu. Workbench page
object navigates Java → <item> accordingly. Verified: CreateNewFileIT and
CreateJavaArtifactsIT both pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ath; index freshness

The Java editor was slow to "enable" features after every jar restart because JDT.LS
re-indexed the whole platform classpath each time. Causes and fixes:

- JdtLsManager wiped the JDT.LS data/index dir on every start. Since ClassPathIndex
  now extracts to a stable cache dir, the index only goes stale when the classpath
  actually changes. Wipe is now guarded by a classpath fingerprint (SHA-256 of the
  sorted classpath entries) stored next to the data dir: matching fingerprint → reuse
  the index (warm, fast restart); mismatch/first run → rebuild once.
- Pre-warm the (cached) compile classpath on the boot virtual thread so the first Java
  file open doesn't pay the multi-second materialisation.
- After didOpen, send workspace/didChangeWatchedFiles(Created) so JDT.LS's project
  model includes just-created files immediately (a fresh interface is now offered in a
  sibling class without waiting for a rebuild).
- Dropped java.completion.maxResults (it equalled JDT.LS's default and only risked
  trimming relevant results such as the project's own types).

Verified: CreateJavaArtifactsIT + CreateNewFileIT pass; logs show "Pre-warmed compile
classpath" and the fingerprint-guarded "Building/Reusing JDT.LS index".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@iliyan-velichkov iliyan-velichkov changed the title feat(ide): IntelliJ-style Java authoring — New → Java scaffolding + full Monaco Java IntelliSense feat(ide): IntelliJ-style Java development in the web IDE — New→Java scaffolding, full JDT.LS IntelliSense, refactoring & performance Jun 24, 2026
iliyan-velichkov and others added 4 commits June 24, 2026 10:00
…on save, Surround With

- Enable JDT.LS postfix completion (expr.var/.for/.fori/.sout/.null/.notnull/.cast/...).
- Organize imports on save for Java: the Save action now runs organize-imports →
  format → save (Java only; failures still fall through to save). TS/other files
  keep format-then-save.
- Add a "Java: Surround With / Refactor..." editor action (Cmd/Ctrl+Alt+T) that opens
  the refactor picker (surround try-catch/if, extract, ...).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enable `semanticHighlighting.enabled` and give every theme an explicit
`semanticHighlighting: true` flag plus colour rules for the full JDT.LS legend
(namespace/class/interface/enum/type/typeParameter/annotation/enumMember/
method/field/property/variable/parameter) AND keyword/modifier — mapping the
modifier-bearing keyword tokens is what stops keywords blanking out under the
semantic layer (the earlier regression). Adds a custom `blimpkit-light` theme
(base vs) so light mode gets the same explicit rules instead of bare vs-light;
dark uses blimpkit-dark/classic-dark. Palettes mirror VS Code dark+/light+.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…(Cmd/Ctrl+T)

Views outside the Monaco iframe can't reuse the editor's per-iframe LSP socket, so
add an HTTP facade that drives the shared JDT.LS instance directly:

- JavaLspQueryEndpoint (/services/ide/java-lsp): GET /symbol plus
  call-hierarchy/{prepare,incoming,outgoing} and type-hierarchy/{prepare,supertypes,
  subtypes}. Each getOrStart → ensureInitialized → sendRequest, returning the LSP
  result; URIs travel as virtual file:///workspace/<ws>/... (bridge-translated).
- Advertise workspace/symbol + textDocument/{callHierarchy,typeHierarchy} in BOTH
  the server-side initialize and the editor client initialize, so the capabilities
  survive whichever side last (re)initializes the shared JDT.LS process.
- New view-java-symbols (left region): debounced workspace symbol search, kind
  icons, container + path subtitle, click-to-open at the symbol's line. Registered
  in components/pom.xml, group-ide, and the workbench views list.
- Editor action "Java: Go to Symbol in Workspace..." (Cmd/Ctrl+T) focuses the view
  and seeds it with the current selection / word under cursor.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New bottom-region view-java-hierarchy driven by the JavaLspQueryEndpoint facade:

- Editor actions "Show Call Hierarchy" (Ctrl+Alt+H) and "Show Type Hierarchy"
  (Ctrl+H) post java.hierarchy.show {kind, workspace, uri, line, character} for the
  symbol under the cursor and focus the panel.
- The panel resolves the root via prepare, then lazily expands each node:
  call -> incoming/outgoing, type -> supertypes/subtypes, with a toolbar toggle
  (Callers/Callees, Supertypes/Subtypes). Custom flat-tree model (depth-indented
  rows, lazy fetch on expand) — no jstree dependency. Click navigates to the node's
  declaration. Registered in components/pom.xml, group-ide, and the workbench views.
- Fix view-java-symbols path mapping: strip only the file:///workspace prefix so the
  workspace segment is preserved (/<ws>/<proj>/File.java), matching the editor's
  resourcePath; the previous version dropped the workspace and opened a wrong path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
iliyan-velichkov and others added 3 commits June 24, 2026 15:16
… race

Go to Symbol in Workspace is redundant with Go to References / Implementations
(and its view's AngularJS failed to bootstrap), so remove it entirely:
- delete view-java-symbols and its registrations (components/pom.xml, group-ide,
  workbench views list);
- drop the editor "Go to Symbol in Workspace" action;
- drop the now-dead GET /symbol endpoint and the workspace/symbol capability from
  both the server-side and editor-client initialize.

Call/Type Hierarchy did nothing on right-click: the editor posted java.hierarchy.show
immediately after openView, before the lazily-loaded panel registered its listener,
so the request was missed. Re-post the request (0/400/1200ms, same pattern as
javaLspOpenFile's reveal re-post) and dedupe identical requests in the panel within a
3s window so the retries don't refetch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…Boot 4's Jackson 3 converter

Every call/type hierarchy POST 500'd before reaching the handler:
HttpMessageConversionException "Cannot construct instance of
com.fasterxml.jackson.databind.JsonNode". Spring Boot 4's default HTTP message
converter is Jackson 3 (tools.jackson.databind) and cannot bind a request body to a
Jackson 2 (com.fasterxml.jackson) JsonNode, which is what JdtLsInstance uses.

Keep the controller boundary off Jackson-2 types: accept the body as a raw String,
parse it with this module's own Jackson 2 ObjectMapper, and return raw JSON as a
String with application/json. No JsonNode parameter or return value is exposed to
Spring's converter anymore.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 96 javascript quality alerts (useless-assignment-to-local, trivial-conditional,
unused-local-variable) all originate in java-lsp-client.js, which is the esbuild
output of java-lsp-client.ts and embeds vendored vscode-languageserver protocol/types.
The hand-written .ts source is still analysed; only the generated bundle is ignored.

The 4 java/log-injection alerts in JdtLsManager are dismissed as false positives:
the logged username/workspace already pass through sanitize() which strips [\r\n\t]
(the CWE-117 vector); CodeQL just doesn't recognise the custom sanitizer helper.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@iliyan-velichkov iliyan-velichkov self-assigned this Jun 24, 2026
@iliyan-velichkov iliyan-velichkov changed the title feat(ide): IntelliJ-style Java development in the web IDE — New→Java scaffolding, full JDT.LS IntelliSense, refactoring & performance feat(ide): IntelliJ-grade Java in the web IDE — New→Java scaffolding, full JDT.LS IntelliSense, refactoring, Call/Type Hierarchy & performance Jun 24, 2026
… executeJavaScript

clickCascadingMenuItem navigated the menu via one injected DOM script, which stuck
out against the rest of BrowserImpl (built on Selenide element APIs). Rewrite it
using Selenide: locate the open context menu once (findElementInAllFrames leaves the
driver in the menu's iframe), then hover each intermediate submenu title to expand
its flyout — BlimpKit expands on mouseenter and keeps it open while the pointer moves
into the flyout — and click the leaf. Staying within the menu's frame via the returned
element handle is the crux: re-searching per step restarts at defaultContent() and
would close the menu (the original reason a single script was used).

Removes CASCADE_MENU_SCRIPT (the only Selenide.executeJavaScript usage in the class).
Verified: CreateJavaArtifactsIT passes headless.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants