Skip to content

fix(properties): scope completion query characters to property nodes#289

Merged
tartarughina merged 1 commit into
zed-extensions:mainfrom
luceat-lux-vestra:fix/properties-completion-query-chars-287
Jul 22, 2026
Merged

fix(properties): scope completion query characters to property nodes#289
tartarughina merged 1 commit into
zed-extensions:mainfrom
luceat-lux-vestra:fix/properties-completion-query-chars-287

Conversation

@luceat-lux-vestra

@luceat-lux-vestra luceat-lux-vestra commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Fixes #287.

Problem

Typing a dotted key such as server.p in application.properties pushes server.port out of the completion menu entirely, while unrelated deeper keys (server.ssl.key-password, server.tomcat.max-part-header-size) rank at the top.

The cause is on the query side, not the ranking side. Zed builds the fuzzy query from the surrounding word at the cursor (Editor::completion_querysurrounding_word(offset, Some(CharScopeContext::Completion))), and . is not a word character for the Properties language. So at server.p the query collapses to p, every candidate containing a p matches, and the exact prefix match loses.

This is independent of what the server advertises. The completions here come from the Spring Boot Language Server — the same server that backs the VS Code Spring Boot Tools extension — which I reach in Zed through zed-spring-tools. It returns server.port as its first item with sortText: "00000"; the item is present in the LSP response and simply never surfaces in the menu.

Fix

Declare completion_query_characters for Properties so the query is the whole dotted key. As @tartarughina suggested, the override is scoped to property rather than string. The setting only takes effect through an override scope, so this also adds the matching overrides.scm — without it the config.toml block is inert.

The capture must be .inclusive. A key is typed left-to-right, so the cursor sits at the end offset of the property node, and SyntaxLayer::override_id skips non-inclusive captures when offset >= range.end.

Verification

Driven in Zed 1.11.3+stable.326 against a Spring Boot 3 project with the official Java extension and jdtls running, so the completions are classpath-backed.

Cursor at the end of server.p:

overrides.scm extracted query result
(file absent) p server.port absent; server.ssl.key-password first
(property) @property p unchanged — override never applies at the node's end offset
(property) @property.inclusive server.p server.port first, server. highlighted on every item

Before — at server.p, server.port is absent from the menu and server.ssl.key-password ranks first:

Before

After — same cursor with (property) @property.inclusive, server.port is the first item:

After

Known residual

Two things are out of reach from the extension:

  1. If the property is on the final line without a trailing newline, the override still does not apply. Files ending in a newline (the default on save) are unaffected.
  2. Below the top hit the order is still Zed's fuzzy score rather than the server's sortTextsort_score is compared before sort_text in sort_string_matches, and deprecated items are not deprioritised, so a deprecated key can rank third. I've filed that separately as LSP sortText is effectively ignored when ranking completions zed-industries/zed#61349.

Typing a dotted key such as `server.p` ranked unrelated deeper keys above
`server.port`, because Zed built its fuzzy query from the surrounding word
only, and `.` was not a word character for Properties. The query collapsed
to `p`, so the server's `sortText` ordering was discarded and the exact
prefix match dropped out of the visible list.

Declare `completion_query_characters` for the Properties language so the
query is the whole dotted key. The setting only takes effect through an
override scope, so add the matching `overrides.scm`.

The capture must be `.inclusive`: a key is typed left-to-right, so the
cursor sits at the end offset of the `property` node, and Zed's
`SyntaxLayer::override_id` excludes that offset for non-inclusive captures.
Verified in Zed 1.11.3 against a Spring Boot project — with a plain
`@property` capture the query stays `p` and `server.port` is absent from
the menu; with `@property.inclusive` the query becomes `server.p` and
`server.port` ranks first.

Fixes zed-extensions#287
Copilot AI review requested due to automatic review settings July 20, 2026 16:22
@cla-bot cla-bot Bot added the cla-signed label Jul 20, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@tartarughina

Copy link
Copy Markdown
Collaborator

@luceat-lux-vestra thanks for the PR. Let's please add the issue you opened against Zed for the completions' sorting and could you add screenshots of the before and after? Other than that the code and the testing you've done are good

@luceat-lux-vestra

Copy link
Copy Markdown
Contributor Author

Added the upstream Zed issue and before/after screenshots to the PR description. Thanks for the review!

@tartarughina
tartarughina merged commit f0fa2d8 into zed-extensions:main Jul 22, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Properties completions lose qualified-prefix ranking after dots

3 participants