Problem
MicroProfile snippet completion items (e.g. mpliveness, mpreadiness) are only surfaced in VS Code when the user types the exact prefix of their filterText value (e.g. mp). Typing a meaningful word fragment from the human-readable label like live, ven, or readi returns nothing, even though those same triggers work correctly in IntelliJ (LSP4IJ) and Eclipse (LSP4E).
Steps to reproduce
- Open any Java file in a MicroProfile project in VS Code.
- Trigger code completion and type
live.
- Expected:
mpliveness appears in the completion list.
- Actual: No MicroProfile snippet appears.
Typing mp does surface the item.
Root Cause
SnippetRegistry.java in lsp4mp sets filterText = "mpliveness" (all-lowercase, no word boundaries)
on every MP snippet completion item. All three IDEs receive the same LSP payload. Vs Code's fuzzyScore requires matched characters to start at a word boundary in order for the completion to pop up. Since 'mpliveness' is a lowercase string with no other boundaries, only prefixes match to the completion.
Eclipse and IntelliJ have their own LSP client layers (LSP4E and LSP4IJ) that do smarter matching. LSP4E uses "ordered subsequence matching", and LSP4IJ registers filterText and label as lookup strings to let IntelliJ match against both. VS Code dies not have an equivalent layer like this.
| IDE |
How it matches partial words |
Result |
| Eclipse (LSP4E) |
CompletionProposalTools.java does ordered subsequence matching on filterText: l-i-v-e appears in order inside mpliveness |
works |
| IntelliJ (LSP4IJ) |
LSPCompletionProposal.getAllLookupStrings() returns both filterText and the item label and IntelliJ's engine matches against either string |
works |
| VS Code |
Runs fuzzyScore on filterText only; no equivalent client-side pre-processing layer |
broken |
VS Code's fuzzyScore relies on camelCase / word-boundary detection to weight non-prefix matches.
The string "mpliveness" is entirely lowercase with no boundaries, so live scores 0 and the item
is filtered out. The same logic means even weak matches like ven (subsequence of liveness) do
not register.
Potential Fix
Adding a middleware in vscode-microprofile that rewrites filterText on MP snippet completion items to the item's label ('mpliveness' -> "MicroProfile liveness check", "mpreadiness" -> "Microprofile readiness check") before the items are returned to VS Code. This gives VS Code's fuzzy engine a string with real word boundaries to match against, so typing 'live' matches liveness. Even 'ven' can should then match via weak matching set in VS Code that doesn't register on just lowercase strings without boundary. This mirror LSP4IJ achieves by registering filterText and label as lookup strings and what LSP4E does through ordered subsequence matching. The middleware would be VS Code's equal to an extra handling layer that IntelliJ and Eclipse have.
What still needs verification
The exact fuzzyScore threshold behaviour for weak word-interior matches should be confirmed
by implementing the middleware locally and testing live / ven / readi interactively, since
VS Code's weak-match path is only active when the scoring string has real word boundaries.
This problem was found after investigation of the following issue in liberty-tools-vscode: OpenLiberty/liberty-tools-vscode#341
Problem
MicroProfile snippet completion items (e.g.
mpliveness,mpreadiness) are only surfaced in VS Code when the user types the exact prefix of theirfilterTextvalue (e.g.mp). Typing a meaningful word fragment from the human-readable label likelive,ven, orreadireturns nothing, even though those same triggers work correctly in IntelliJ (LSP4IJ) and Eclipse (LSP4E).Steps to reproduce
live.mplivenessappears in the completion list.Typing
mpdoes surface the item.Root Cause
SnippetRegistry.javain lsp4mp setsfilterText = "mpliveness"(all-lowercase, no word boundaries)on every MP snippet completion item. All three IDEs receive the same LSP payload. Vs Code's fuzzyScore requires matched characters to start at a word boundary in order for the completion to pop up. Since 'mpliveness' is a lowercase string with no other boundaries, only prefixes match to the completion.
Eclipse and IntelliJ have their own LSP client layers (LSP4E and LSP4IJ) that do smarter matching. LSP4E uses "ordered subsequence matching", and LSP4IJ registers filterText and label as lookup strings to let IntelliJ match against both. VS Code dies not have an equivalent layer like this.
CompletionProposalTools.javadoes ordered subsequence matching onfilterText:l-i-v-eappears in order insidemplivenessLSPCompletionProposal.getAllLookupStrings()returns bothfilterTextand the itemlabeland IntelliJ's engine matches against either stringfuzzyScoreonfilterTextonly; no equivalent client-side pre-processing layerVS Code's
fuzzyScorerelies on camelCase / word-boundary detection to weight non-prefix matches.The string
"mpliveness"is entirely lowercase with no boundaries, solivescores 0 and the itemis filtered out. The same logic means even weak matches like
ven(subsequence of liveness) donot register.
Potential Fix
Adding a middleware in vscode-microprofile that rewrites filterText on MP snippet completion items to the item's label ('mpliveness' -> "MicroProfile liveness check", "mpreadiness" -> "Microprofile readiness check") before the items are returned to VS Code. This gives VS Code's fuzzy engine a string with real word boundaries to match against, so typing 'live' matches liveness. Even 'ven' can should then match via weak matching set in VS Code that doesn't register on just lowercase strings without boundary. This mirror LSP4IJ achieves by registering filterText and label as lookup strings and what LSP4E does through ordered subsequence matching. The middleware would be VS Code's equal to an extra handling layer that IntelliJ and Eclipse have.
What still needs verification
The exact fuzzyScore threshold behaviour for weak word-interior matches should be confirmed
by implementing the middleware locally and testing live / ven / readi interactively, since
VS Code's weak-match path is only active when the scoring string has real word boundaries.
This problem was found after investigation of the following issue in liberty-tools-vscode: OpenLiberty/liberty-tools-vscode#341