Skip to content

Commit 3fa653b

Browse files
16bit-ykikoclaude
andauthored
feat(completion): mark deprecated symbols with strikethrough (#414)
## Summary - Check `CXAvailability_Deprecated` on `CodeCompletionResult` and set `CompletionItemTag::Deprecated` - Editors render deprecated completions with a strikethrough on the label ## Test plan - [x] `DeprecatedTag` — `[[deprecated]]` function gets the tag - [x] `NotDeprecated` — normal function has no Deprecated tag - [x] All 491 unit tests pass - [x] `pixi run format` clean Stacked on #411. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Code completion now marks deprecated declarations with a deprecated tag so users can see deprecated items in completion lists. * **Tests** * Added unit tests ensuring deprecated declarations produce completion items with the deprecated tag and non-deprecated items do not. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 592b374 commit 3fa653b

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

src/feature/code_completion.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,8 @@ class CodeCompletionCollector final : public clang::CodeCompleteConsumer {
296296
llvm::StringRef overload_key,
297297
llvm::StringRef signature = {},
298298
llvm::StringRef return_type = {},
299-
bool is_snippet = false) {
299+
bool is_snippet = false,
300+
bool is_deprecated = false) {
300301
if(label.empty()) {
301302
return;
302303
}
@@ -327,6 +328,9 @@ class CodeCompletionCollector final : public clang::CodeCompleteConsumer {
327328
}
328329
item.label_details = std::move(details);
329330
}
331+
if(is_deprecated) {
332+
item.tags = std::vector{protocol::CompletionItemTag::Deprecated};
333+
}
330334
overloads.push_back({
331335
.item = std::move(item),
332336
.score = *score,
@@ -355,6 +359,9 @@ class CodeCompletionCollector final : public clang::CodeCompleteConsumer {
355359
}
356360
item.label_details = std::move(details);
357361
}
362+
if(is_deprecated) {
363+
item.tags = std::vector{protocol::CompletionItemTag::Deprecated};
364+
}
358365
collected.push_back(std::move(item));
359366
};
360367

@@ -431,13 +438,15 @@ class CodeCompletionCollector final : public clang::CodeCompleteConsumer {
431438

432439
bool has_snippet = !snippet.empty();
433440
auto insert = has_snippet ? llvm::StringRef(snippet) : llvm::StringRef(label);
441+
bool deprecated = candidate.Availability == CXAvailability_Deprecated;
434442
try_add(label,
435443
kind,
436444
insert,
437445
qualified_name.str(),
438446
signature,
439447
return_type,
440-
has_snippet);
448+
has_snippet,
449+
deprecated);
441450
break;
442451
}
443452
}

tests/unit/feature/code_completion_tests.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,33 @@ void bar() {
233233
}
234234
}
235235

236+
TEST_CASE(DeprecatedTag) {
237+
code_complete(R"cpp(
238+
[[deprecated]] int foooo(int x);
239+
int z = fo$(pos)
240+
)cpp");
241+
242+
auto it = find_item("foooo");
243+
ASSERT_TRUE(it != items.end());
244+
ASSERT_TRUE(it->tags.has_value());
245+
auto& tags = *it->tags;
246+
ASSERT_TRUE(std::ranges::find(tags, protocol::CompletionItemTag::Deprecated) != tags.end());
247+
}
248+
249+
TEST_CASE(NotDeprecated) {
250+
code_complete(R"cpp(
251+
int foooo(int x);
252+
int z = fo$(pos)
253+
)cpp");
254+
255+
auto it = find_item("foooo");
256+
ASSERT_TRUE(it != items.end());
257+
// Non-deprecated should have no Deprecated tag.
258+
ASSERT_TRUE(!it->tags.has_value() ||
259+
std::ranges::find(*it->tags, protocol::CompletionItemTag::Deprecated) ==
260+
it->tags->end());
261+
}
262+
236263
TEST_CASE(NoBundleOverloads) {
237264
feature::CodeCompletionOptions opts;
238265
opts.bundle_overloads = false;

0 commit comments

Comments
 (0)