Port SelectionTree from clangd to clice (#166)

This commit is contained in:
ykiko
2025-08-05 22:10:08 +08:00
committed by GitHub
parent 139eaa44f7
commit 072ddb3a59
25 changed files with 2419 additions and 1182 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -134,6 +134,10 @@ auto CompilationUnit::expansion_location(clang::SourceLocation location) -> clan
return impl->src_mgr.getExpansionLoc(location);
}
auto CompilationUnit::file_location(clang::SourceLocation location) -> clang::SourceLocation {
return impl->src_mgr.getFileLoc(location);
}
auto CompilationUnit::include_location(clang::FileID fid) -> clang::SourceLocation {
return impl->src_mgr.getIncludeLoc(fid);
}
@@ -142,15 +146,34 @@ auto CompilationUnit::presumed_location(clang::SourceLocation location) -> clang
return impl->src_mgr.getPresumedLoc(location, false);
}
auto CompilationUnit::create_location(clang::FileID fid, std::uint32_t offset)
-> clang::SourceLocation {
return impl->src_mgr.getComposedLoc(fid, offset);
}
auto CompilationUnit::spelled_tokens(clang::FileID fid) -> llvm::ArrayRef<clang::syntax::Token> {
return impl->buffer->spelledTokens(fid);
}
auto CompilationUnit::spelled_tokens_touch(clang::SourceLocation location)
-> llvm::ArrayRef<clang::syntax::Token> {
return clang::syntax::spelledTokensTouching(location, *impl->buffer);
}
auto CompilationUnit::expanded_tokens() -> llvm::ArrayRef<clang::syntax::Token> {
return impl->buffer->expandedTokens();
}
auto CompilationUnit::expanded_tokens(clang::SourceRange range)
-> llvm::ArrayRef<clang::syntax::Token> {
return impl->buffer->expandedTokens(range);
}
auto CompilationUnit::expansions_overlapping(llvm::ArrayRef<clang::syntax::Token> spelled_tokens)
-> std::vector<clang::syntax::TokenBuffer::Expansion> {
return impl->buffer->expansionsOverlapping(spelled_tokens);
}
auto CompilationUnit::token_length(clang::SourceLocation location) -> std::uint32_t {
return clang::Lexer::MeasureTokenLength(location, impl->src_mgr, impl->instance->getLangOpts());
}
@@ -273,4 +296,8 @@ clang::ASTContext& CompilationUnit::context() {
return impl->instance->getASTContext();
}
clang::syntax::TokenBuffer& CompilationUnit::token_buffer() {
return *impl->buffer;
}
} // namespace clice

View File

@@ -60,80 +60,6 @@ std::string getSourceCode(CompilationUnit& unit, const clang::NamedDecl* decl) {
return "";
}
struct HoversStorage : Hovers {
llvm::DenseMap<const void*, uint32_t> cache;
void add(CompilationUnit& unit, const clang::NamedDecl* decl, LocalSourceRange range) {
auto [iter, success] = cache.try_emplace(decl, hovers.size());
if(success) {
hovers.emplace_back(hover(unit, decl));
}
occurrences.emplace_back(range, iter->second);
}
void sort() {
std::vector<uint32_t> hoverMap(hovers.size());
{
std::vector<uint32_t> new2old(hovers.size());
for(uint32_t i = 0; i < hovers.size(); ++i) {
new2old[i] = i;
}
ranges::sort(views::zip(hovers, new2old), refl::less, [](const auto& element) {
return std::get<0>(element);
});
for(uint32_t i = 0; i < hovers.size(); ++i) {
hoverMap[new2old[i]] = i;
}
}
for(auto& occurrence: occurrences) {
occurrence.index = hoverMap[occurrence.index];
}
ranges::sort(occurrences, refl::less, [](const auto& item) { return item.range; });
}
};
/// For index all hover information in the given unit.
class HoverCollector : public SemanticVisitor<HoverCollector> {
public:
HoverCollector(CompilationUnit& unit) : SemanticVisitor<HoverCollector>(unit, false) {}
void handleDeclOccurrence(const clang::NamedDecl* decl,
RelationKind kind,
clang::SourceLocation location) {
/// FIXME: Currently we only handle file location.
if(location.isMacroID()) {
return;
}
decl = normalize(decl);
auto [fid, range] = unit.decompose_range(location);
auto& file = files[fid];
file.add(unit, decl, range);
}
auto build() {
index::Shared<Hovers> hovers;
run();
for(auto& [fid, storage]: files) {
storage.sort();
hovers[fid] = std::move(static_cast<Hovers&>(storage));
}
return hovers;
}
private:
index::Shared<HoversStorage> files;
};
} // namespace
Hover hover(CompilationUnit& unit, const clang::NamedDecl* decl) {
@@ -147,9 +73,21 @@ Hover hover(CompilationUnit& unit, const clang::NamedDecl* decl) {
};
}
index::Shared<Hovers> indexHover(CompilationUnit& unit) {
HoverCollector collector(unit);
return collector.build();
Hover hover(CompilationUnit& unit, std::uint32_t offset) {
Hover info;
auto tree = SelectionTree::create_right(unit, {offset, offset});
if(auto node = tree.common_ancestor()) {
if(auto decl = node->get<clang::NamedDecl>()) {
return hover(unit, decl);
} else if(auto ref = node->get<clang::DeclRefExpr>()) {
return hover(unit, ref->getDecl());
}
/// TODO: add ....
}
return Hover{};
}
} // namespace clice::feature

View File

@@ -1,20 +1,47 @@
#include "Server/Server.h"
#include "Server/Convert.h"
#include "Compiler/Compilation.h"
#include "Feature/Hover.h"
namespace clice {
async::Task<json::Value> Server::on_hover(proto::HoverParams params) {
auto path = mapping.to_path(params.textDocument.uri);
auto opening_file = &opening_files[path];
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto offset = to_offset(kind, opening_file->content, params.position);
opening_file = &opening_files[path];
auto content = opening_file->content;
auto ast = opening_file->ast;
if(!ast) {
co_return json::Value(nullptr);
}
co_return co_await async::submit([kind = this->kind, offset, &ast] {
auto hover = feature::hover(*ast, offset);
proto::Hover result;
result.contents.kind = "markdown";
result.contents.value = std::format("{}: {}", hover.kind.name(), hover.name);
return json::serialize(result);
});
}
async::Task<json::Value> Server::on_semantic_token(proto::SemanticTokensParams params) {
auto path = mapping.to_path(params.textDocument.uri);
auto openFile = &opening_files[path];
auto guard = co_await openFile->ast_built_lock.try_lock();
auto opening_file = &opening_files[path];
auto guard = co_await opening_file->ast_built_lock.try_lock();
openFile = &opening_files[path];
auto content = openFile->content;
auto ast = openFile->ast;
opening_file = &opening_files[path];
auto content = opening_file->content;
auto ast = opening_file->ast;
if(!ast) {
co_return "";
co_return json::Value(nullptr);
}
co_return co_await async::submit([kind = this->kind, &ast] {

View File

@@ -39,6 +39,9 @@ async::Task<json::Value> Server::on_initialize(proto::InitializeParams params) {
capabilities.textDocumentSync.change = proto::TextDocumentSyncKind::Full;
capabilities.textDocumentSync.save = true;
/// Hover
capabilities.hoverProvider = true;
/// Completion
capabilities.completionProvider.triggerCharacters = {".", "<", ">", ":", "\"", "/", "*"};
capabilities.completionProvider.resolveProvider = false;

View File

@@ -63,6 +63,7 @@ Server::Server() {
register_callback<&Server::on_did_save>("textDocument/didSave");
register_callback<&Server::on_did_close>("textDocument/didClose");
register_callback<&Server::on_hover>("textDocument/hover");
register_callback<&Server::on_completion>("textDocument/completion");
register_callback<&Server::on_semantic_token>("textDocument/semanticTokens/full");
}