Refactor and clean (#189)

This commit is contained in:
ykiko
2025-08-24 15:03:07 +08:00
committed by GitHub
parent cbb210c027
commit ce4b16ce30
12 changed files with 143 additions and 56 deletions

View File

@@ -9,6 +9,41 @@ namespace clice::feature {
namespace {
std::string symbol_detail(clang::ASTContext& Ctx, const clang::NamedDecl& ND) {
clang::PrintingPolicy policy(Ctx.getPrintingPolicy());
policy.SuppressScope = true;
policy.SuppressUnwrittenScope = true;
policy.AnonymousTagLocations = false;
policy.PolishForDeclaration = true;
std::string detail;
llvm::raw_string_ostream os(detail);
if(ND.getDescribedTemplateParams()) {
os << "template ";
}
if(const auto* VD = dyn_cast<clang::ValueDecl>(&ND)) {
// FIXME: better printing for dependent type
if(isa<clang::CXXConstructorDecl>(VD)) {
std::string type = VD->getType().getAsString(policy);
// Print constructor type as "(int)" instead of "void (int)".
llvm::StringRef without_void = type;
without_void.consume_front("void ");
os << without_void;
} else if(!isa<clang::CXXDestructorDecl>(VD)) {
VD->getType().print(os, policy);
}
} else if(const auto* TD = dyn_cast<clang::TagDecl>(&ND)) {
os << TD->getKindName();
} else if(isa<clang::TypedefNameDecl>(&ND)) {
os << "type alias";
} else if(isa<clang::ConceptDecl>(&ND)) {
os << "concept";
}
return detail;
}
/// Use DFS to traverse the AST and collect document symbols.
class DocumentSymbolCollector : public FilteredASTVisitor<DocumentSymbolCollector> {
@@ -50,8 +85,12 @@ public:
}
auto ND = llvm::cast<clang::NamedDecl>(decl);
auto [fid, selectionRange] =
auto [fid, selection_range] =
unit.decompose_range(unit.expansion_location(ND->getLocation()));
auto [fid2, range] = unit.decompose_expansion_range(ND->getSourceRange());
if(fid != fid2) {
return true;
}
auto& frame = interested_only ? result : sharedResult[fid];
auto cursor = frame.cursor;
@@ -59,9 +98,10 @@ public:
/// Add new symbol.
auto& symbol = frame.cursor->emplace_back();
symbol.kind = SymbolKind::from(decl);
symbol.name = ast::name_of(ND);
symbol.selectionRange = selectionRange;
symbol.range = selectionRange;
symbol.name = ast::display_name_of(ND);
symbol.detail = symbol_detail(unit.context(), *ND);
symbol.selectionRange = selection_range;
symbol.range = range;
/// Adjust the node.
frame.cursor = &symbol.children;

View File

@@ -879,9 +879,9 @@ private:
} // namespace
auto inlay_hint(CompilationUnit& unit,
LocalSourceRange target,
const config::InlayHintsOptions& options) -> std::vector<InlayHint> {
auto inlay_hints(CompilationUnit& unit,
LocalSourceRange target,
const config::InlayHintsOptions& options) -> std::vector<InlayHint> {
std::vector<InlayHint> hints;
Builder builder(hints, unit, target, options);

View File

@@ -253,7 +253,7 @@ SemanticTokens semantic_tokens(CompilationUnit& unit) {
return std::move(collector.result);
}
index::Shared<SemanticTokens> indexSemanticToken(CompilationUnit& unit) {
index::Shared<SemanticTokens> index_semantic_token(CompilationUnit& unit) {
SemanticTokensCollector collector(unit, false);
for(auto fid: unit.files()) {
collector.highlight(fid);

View File

@@ -61,7 +61,7 @@ feature::DocumentSymbols FeatureIndex::documentSymbols() const {
Shared<std::vector<char>> FeatureIndex::build(CompilationUnit& unit) {
Shared<memory::FeatureIndex> indices;
for(auto&& [fid, result]: feature::indexSemanticToken(unit)) {
for(auto&& [fid, result]: feature::index_semantic_token(unit)) {
indices[fid].tokens = std::move(result);
}

View File

@@ -47,8 +47,9 @@ void Server::load_cache_info() {
auto mtime = object->getNumber("mtime");
auto deps = object->getArray("deps");
auto arguments = object->getArray("arguments");
auto includes = object->get("includes");
if(!file || !path || !preamble || !mtime || !deps || !arguments) {
if(!file || !path || !preamble || !mtime || !deps || !arguments || !includes) {
continue;
}
@@ -67,7 +68,10 @@ void Server::load_cache_info() {
}
/// Update the PCH info.
opening_files.get_or_add(*file)->pch = std::move(info);
auto opening_file = opening_files.get_or_add(*file);
opening_file->pch = std::move(info);
opening_file->pch_includes =
json::deserialize<decltype(opening_file->pch_includes)>(*includes);
}
}
@@ -92,6 +96,7 @@ void Server::save_cache_info() {
object["mtime"] = pch.mtime;
object["deps"] = json::serialize(pch.deps);
object["arguments"] = json::serialize(pch.arguments);
object["includes"] = json::serialize(open_file->pch_includes);
json["pchs"].getAsArray()->emplace_back(std::move(object));
}
@@ -313,6 +318,15 @@ async::Task<> Server::build_ast(std::string path, std::string content) {
co_return;
}
/// Send diagnostics
auto diagnostics = co_await async::submit(
[&, kind = this->kind] { return feature::diagnostics(kind, mapping, *ast); });
co_await notify("textDocument/publishDiagnostics",
json::Object{
{"uri", mapping.to_uri(path) },
{"diagnostics", std::move(diagnostics)},
});
/// FIXME: Index the source file.
/// co_await indexer.index(*ast);
@@ -327,6 +341,7 @@ async::Task<> Server::build_ast(std::string path, std::string content) {
async::Task<std::shared_ptr<OpenFile>> Server::add_document(std::string path, std::string content) {
auto& openFile = opening_files.get_or_add(path);
openFile->version += 1;
openFile->content = content;
auto& task = openFile->ast_build_task;
@@ -350,33 +365,15 @@ async::Task<std::shared_ptr<OpenFile>> Server::add_document(std::string path, st
co_return openFile;
}
async::Task<> Server::publish_diagnostics(std::string path, std::shared_ptr<OpenFile> file) {
auto guard = co_await file->ast_built_lock.try_lock();
if(file->ast) {
auto diagnostics = feature::diagnostics(kind, mapping, *file->ast);
co_await notify("textDocument/publishDiagnostics",
json::Object{
{"uri", mapping.to_uri(path) },
{"diagnostics", std::move(diagnostics)},
});
}
}
async::Task<> Server::on_did_open(proto::DidOpenTextDocumentParams params) {
auto path = mapping.to_path(params.textDocument.uri);
auto file = co_await add_document(path, std::move(params.textDocument.text));
if(file->diagnostics) {
co_await publish_diagnostics(path, std::move(file));
}
co_return;
}
async::Task<> Server::on_did_change(proto::DidChangeTextDocumentParams params) {
auto path = mapping.to_path(params.textDocument.uri);
auto file = co_await add_document(path, std::move(params.contentChanges[0].text));
if(file->diagnostics) {
co_await publish_diagnostics(path, std::move(file));
}
co_return;
}

View File

@@ -43,21 +43,26 @@ auto Server::on_completion(proto::CompletionParams params) -> Result {
auto Server::on_hover(proto::HoverParams params) -> Result {
auto path = mapping.to_path(params.textDocument.uri);
auto opening_file = opening_files.get_or_add(path);
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto version = opening_file->version;
auto offset = to_offset(kind, opening_file->content, params.position);
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto ast = opening_file->ast;
if(!ast) {
if(opening_file->version != version || !ast) {
co_return json::Value(nullptr);
}
auto offset = to_offset(kind, opening_file->content, params.position);
co_return co_await async::submit([kind = this->kind, offset, &ast] {
auto hover = feature::hover(*ast, offset);
if(hover.kind == SymbolKind::Invalid) {
return json::Value(nullptr);
}
proto::Hover result;
result.contents.kind = "markdown";
result.contents.value = std::format("{}: {}", hover.kind.name(), hover.name);
return json::serialize(result);
});
}
@@ -92,10 +97,12 @@ async::Task<json::Value> Server::on_signature_help(proto::SignatureHelpParams pa
auto Server::on_document_symbol(proto::DocumentSymbolParams params) -> Result {
auto path = mapping.to_path(params.textDocument.uri);
auto opening_file = opening_files.get_or_add(path);
auto version = opening_file->version;
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto ast = opening_file->ast;
if(!ast) {
if(opening_file->version != version || !ast) {
co_return json::Value(nullptr);
}
@@ -112,9 +119,7 @@ auto Server::on_document_symbol(proto::DocumentSymbolParams params) -> Result {
proto::DocumentSymbol result;
result.name = std::move(symbol.name);
result.detail = std::move(symbol.detail);
/// FIXME: Add kind map.
result.kind = static_cast<proto::SymbolKind>(symbol.kind.value());
result.kind = proto::kind_map(symbol.kind.kind());
result.range = to_range(symbol.range);
result.selectionRange = to_range(symbol.selectionRange);
@@ -140,10 +145,12 @@ auto Server::on_document_symbol(proto::DocumentSymbolParams params) -> Result {
auto Server::on_document_link(proto::DocumentLinkParams params) -> Result {
auto path = mapping.to_path(params.textDocument.uri);
auto opening_file = opening_files.get_or_add(path);
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto version = opening_file->version;
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto ast = opening_file->ast;
if(!ast) {
if(opening_file->version != version || !ast) {
co_return json::Value(nullptr);
}
@@ -195,10 +202,12 @@ auto Server::on_document_range_format(proto::DocumentRangeFormattingParams param
async::Task<json::Value> Server::on_folding_range(proto::FoldingRangeParams params) {
auto path = mapping.to_path(params.textDocument.uri);
auto opening_file = opening_files.get_or_add(path);
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto version = opening_file->version;
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto ast = opening_file->ast;
if(!ast) {
if(opening_file->version != version || !ast) {
co_return json::Value(nullptr);
}
@@ -233,10 +242,12 @@ async::Task<json::Value> Server::on_folding_range(proto::FoldingRangeParams para
auto Server::on_semantic_token(proto::SemanticTokensParams params) -> Result {
auto path = mapping.to_path(params.textDocument.uri);
auto opening_file = opening_files.get_or_add(path);
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto version = opening_file->version;
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto ast = opening_file->ast;
if(!ast) {
if(opening_file->version != version || !ast) {
co_return json::Value(nullptr);
}
@@ -249,10 +260,12 @@ auto Server::on_semantic_token(proto::SemanticTokensParams params) -> Result {
auto Server::on_inlay_hint(proto::InlayHintParams params) -> Result {
auto path = mapping.to_path(params.textDocument.uri);
auto opening_file = opening_files.get_or_add(path);
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto version = opening_file->version;
auto guard = co_await opening_file->ast_built_lock.try_lock();
auto ast = opening_file->ast;
if(!ast) {
if(opening_file->version != version || !ast) {
co_return json::Value(nullptr);
}
@@ -264,7 +277,7 @@ auto Server::on_inlay_hint(proto::InlayHintParams params) -> Result {
to_offset(kind, content, params.range.end),
};
auto hints = feature::inlay_hint(*ast, range, {});
auto hints = feature::inlay_hints(*ast, range, {});
PositionConverter converter(content, kind);