Refactor and clean (#189)
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user