Skip to content

Commit 8da14ec

Browse files
sam-mccallmemfrob
authored and
memfrob
committed
[clangd][VSCode] Force VSCode to use the ranking provided by clangd.
Summary: Clangd's approach is to provide lots of completions, and let ranking sort them out. This relies on various important signals (Quality.h), without which the large completion lists are extremely spammy. Even with a completion result exactly at the cursor, vscode looks backwards and tries to match the presumed partial-identifier against filterText, and uses the result to rank, with sortText only used as a tiebreak. By prepending the partial-identifier to the filterText, we can force the match to be perfect and so give sortText full control of the ranking. Full sad story: microsoft/language-server-protocol#898 It's possible to do this on the server side too of course, and switch it on with an initialization option. But it's a little easier in the extension, it will get the fix to users of old clangd versions, and other editors Reviewers: hokein Reviewed By: hokein Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D75623
1 parent bae05ce commit 8da14ec

File tree

1 file changed

+27
-1
lines changed
  • clang-tools-extra/clangd/clients/clangd-vscode/src

1 file changed

+27
-1
lines changed

clang-tools-extra/clangd/clients/clangd-vscode/src/extension.ts

+27-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,33 @@ export function activate(context: vscode.ExtensionContext) {
9898
},
9999
initializationOptions: { clangdFileStatus: true },
100100
// Do not switch to output window when clangd returns output
101-
revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never
101+
revealOutputChannelOn: vscodelc.RevealOutputChannelOn.Never,
102+
103+
// We hack up the completion items a bit to prevent VSCode from re-ranking them
104+
// and throwing away all our delicious signals like type information.
105+
//
106+
// VSCode sorts by (fuzzymatch(prefix, item.filterText), item.sortText)
107+
// By adding the prefix to the beginning of the filterText, we get a perfect
108+
// fuzzymatch score for every item.
109+
// The sortText (which reflects clangd ranking) breaks the tie.
110+
//
111+
// We also have to mark the list as incomplete to force retrieving new rankings.
112+
// See https://github.com/microsoft/language-server-protocol/issues/898
113+
middleware: {
114+
provideCompletionItem: async (document, position, context, token, next) => {
115+
// Get the incomplete identifier before the cursor.
116+
let word = document.getWordRangeAtPosition(position);
117+
let prefix = word && document.getText(new vscode.Range(word.start, position));
118+
119+
let list = await next(document, position, context, token);
120+
let items = (Array.isArray(list) ? list : list.items).map(item => {
121+
if (prefix)
122+
item.filterText = prefix + "_" + item.filterText;
123+
return item;
124+
})
125+
return new vscode.CompletionList(items, /*isIncomplete=*/true);
126+
}
127+
},
102128
};
103129

104130
const clangdClient = new ClangdLanguageClient('Clang Language Server',

0 commit comments

Comments
 (0)