Skip to content

Commit fdcaddf

Browse files
committed
A group of fix.
1 parent 23ef393 commit fdcaddf

File tree

6 files changed

+116
-24
lines changed

6 files changed

+116
-24
lines changed

include/Feature/DocumentSymbol.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ struct DocumentSymbol {
2929
using DocumentSymbols = std::vector<DocumentSymbol>;
3030

3131
/// Generate document symbols for only interested file.
32-
DocumentSymbols document_symbols(CompilationUnit& unit);
32+
DocumentSymbols document_symbol(CompilationUnit& unit);
3333

3434
/// Generate document symbols for all file in unit.
3535
index::Shared<DocumentSymbols> index_document_symbol(CompilationUnit& unit);

include/Server/Convert.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,44 @@ inline std::uint32_t to_offset(clice::PositionEncodingKind kind,
256256

257257
namespace clice::proto {
258258

259+
inline SymbolKind kind_map(clice::SymbolKind kind) {
260+
switch(kind.kind()) {
261+
case clice::SymbolKind::Comment: return SymbolKind::String;
262+
case clice::SymbolKind::Number: return SymbolKind::Number;
263+
case clice::SymbolKind::Character: return SymbolKind::String;
264+
case clice::SymbolKind::String: return SymbolKind::String;
265+
case clice::SymbolKind::Keyword: return SymbolKind::Variable;
266+
case clice::SymbolKind::Directive: return SymbolKind::Variable;
267+
case clice::SymbolKind::Header: return SymbolKind::String;
268+
case clice::SymbolKind::Module: return SymbolKind::Module;
269+
case clice::SymbolKind::Macro: return SymbolKind::Function;
270+
case clice::SymbolKind::MacroParameter: return SymbolKind::Variable;
271+
case clice::SymbolKind::Namespace: return SymbolKind::Namespace;
272+
case clice::SymbolKind::Class: return SymbolKind::Class;
273+
case clice::SymbolKind::Struct: return SymbolKind::Struct;
274+
case clice::SymbolKind::Union: return SymbolKind::Class;
275+
case clice::SymbolKind::Enum: return SymbolKind::Enum;
276+
case clice::SymbolKind::Type: return SymbolKind::TypeParameter;
277+
case clice::SymbolKind::Field: return SymbolKind::Field;
278+
case clice::SymbolKind::EnumMember: return SymbolKind::EnumMember;
279+
case clice::SymbolKind::Function: return SymbolKind::Function;
280+
case clice::SymbolKind::Method: return SymbolKind::Method;
281+
case clice::SymbolKind::Variable: return SymbolKind::Variable;
282+
case clice::SymbolKind::Parameter: return SymbolKind::Variable;
283+
case clice::SymbolKind::Label: return SymbolKind::Variable;
284+
case clice::SymbolKind::Concept: return SymbolKind::TypeParameter;
285+
case clice::SymbolKind::Attribute: return SymbolKind::Variable;
286+
case clice::SymbolKind::Operator:
287+
case clice::SymbolKind::Paren:
288+
case clice::SymbolKind::Bracket:
289+
case clice::SymbolKind::Brace:
290+
case clice::SymbolKind::Angle: return SymbolKind::Operator;
291+
case clice::SymbolKind::Conflict:
292+
case clice::SymbolKind::Invalid:
293+
default: return SymbolKind::Null;
294+
}
295+
}
296+
259297
json::Value to_json(clice::PositionEncodingKind kind,
260298
llvm::StringRef content,
261299
llvm::ArrayRef<feature::SemanticToken> tokens);

src/Feature/DocumentSymbol.cpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,41 @@ namespace clice::feature {
99

1010
namespace {
1111

12+
std::string symbol_detail(clang::ASTContext& Ctx, const clang::NamedDecl& ND) {
13+
clang::PrintingPolicy policy(Ctx.getPrintingPolicy());
14+
policy.SuppressScope = true;
15+
policy.SuppressUnwrittenScope = true;
16+
policy.AnonymousTagLocations = false;
17+
policy.PolishForDeclaration = true;
18+
19+
std::string detail;
20+
llvm::raw_string_ostream os(detail);
21+
if(ND.getDescribedTemplateParams()) {
22+
os << "template ";
23+
}
24+
25+
if(const auto* VD = dyn_cast<clang::ValueDecl>(&ND)) {
26+
// FIXME: better printing for dependent type
27+
if(isa<clang::CXXConstructorDecl>(VD)) {
28+
std::string type = VD->getType().getAsString(policy);
29+
// Print constructor type as "(int)" instead of "void (int)".
30+
llvm::StringRef without_void = type;
31+
without_void.consume_front("void ");
32+
os << without_void;
33+
} else if(!isa<clang::CXXDestructorDecl>(VD)) {
34+
VD->getType().print(os, policy);
35+
}
36+
} else if(const auto* TD = dyn_cast<clang::TagDecl>(&ND)) {
37+
os << TD->getKindName();
38+
} else if(isa<clang::TypedefNameDecl>(&ND)) {
39+
os << "type alias";
40+
} else if(isa<clang::ConceptDecl>(&ND)) {
41+
os << "concept";
42+
}
43+
44+
return detail;
45+
}
46+
1247
/// Use DFS to traverse the AST and collect document symbols.
1348
class DocumentSymbolCollector : public FilteredASTVisitor<DocumentSymbolCollector> {
1449

@@ -50,18 +85,23 @@ class DocumentSymbolCollector : public FilteredASTVisitor<DocumentSymbolCollecto
5085
}
5186

5287
auto ND = llvm::cast<clang::NamedDecl>(decl);
53-
auto [fid, selectionRange] =
88+
auto [fid, selection_range] =
5489
unit.decompose_range(unit.expansion_location(ND->getLocation()));
90+
auto [fid2, range] = unit.decompose_expansion_range(ND->getSourceRange());
91+
if(fid != fid2) {
92+
return true;
93+
}
5594

5695
auto& frame = interested_only ? result : sharedResult[fid];
5796
auto cursor = frame.cursor;
5897

5998
/// Add new symbol.
6099
auto& symbol = frame.cursor->emplace_back();
61100
symbol.kind = SymbolKind::from(decl);
62-
symbol.name = ast::name_of(ND);
63-
symbol.selectionRange = selectionRange;
64-
symbol.range = selectionRange;
101+
symbol.name = ast::display_name_of(ND);
102+
symbol.detail = symbol_detail(unit.context(), *ND);
103+
symbol.selectionRange = selection_range;
104+
symbol.range = range;
65105

66106
/// Adjust the node.
67107
frame.cursor = &symbol.children;
@@ -86,7 +126,7 @@ class DocumentSymbolCollector : public FilteredASTVisitor<DocumentSymbolCollecto
86126

87127
} // namespace
88128

89-
DocumentSymbols document_symbols(CompilationUnit& unit) {
129+
DocumentSymbols document_symbol(CompilationUnit& unit) {
90130
DocumentSymbolCollector collector(unit, true);
91131
collector.TraverseDecl(unit.tu());
92132

src/Server/Document.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ async::Task<> Server::build_ast(std::string path, std::string content) {
341341

342342
async::Task<std::shared_ptr<OpenFile>> Server::add_document(std::string path, std::string content) {
343343
auto& openFile = opening_files.get_or_add(path);
344+
openFile->version += 1;
344345
openFile->content = content;
345346

346347
auto& task = openFile->ast_build_task;

src/Server/Feature.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,21 +43,26 @@ auto Server::on_completion(proto::CompletionParams params) -> Result {
4343
auto Server::on_hover(proto::HoverParams params) -> Result {
4444
auto path = mapping.to_path(params.textDocument.uri);
4545
auto opening_file = opening_files.get_or_add(path);
46-
auto guard = co_await opening_file->ast_built_lock.try_lock();
46+
auto version = opening_file->version;
4747

48-
auto offset = to_offset(kind, opening_file->content, params.position);
48+
auto guard = co_await opening_file->ast_built_lock.try_lock();
4949
auto ast = opening_file->ast;
50-
if(!ast) {
50+
51+
if(opening_file->version != version || !ast) {
5152
co_return json::Value(nullptr);
5253
}
5354

55+
auto offset = to_offset(kind, opening_file->content, params.position);
56+
5457
co_return co_await async::submit([kind = this->kind, offset, &ast] {
5558
auto hover = feature::hover(*ast, offset);
59+
if(hover.kind == SymbolKind::Invalid) {
60+
return json::Value(nullptr);
61+
}
5662

5763
proto::Hover result;
5864
result.contents.kind = "markdown";
5965
result.contents.value = std::format("{}: {}", hover.kind.name(), hover.name);
60-
6166
return json::serialize(result);
6267
});
6368
}
@@ -92,10 +97,12 @@ async::Task<json::Value> Server::on_signature_help(proto::SignatureHelpParams pa
9297
auto Server::on_document_symbol(proto::DocumentSymbolParams params) -> Result {
9398
auto path = mapping.to_path(params.textDocument.uri);
9499
auto opening_file = opening_files.get_or_add(path);
100+
auto version = opening_file->version;
95101

96102
auto guard = co_await opening_file->ast_built_lock.try_lock();
97103
auto ast = opening_file->ast;
98-
if(!ast) {
104+
105+
if(opening_file->version != version || !ast) {
99106
co_return json::Value(nullptr);
100107
}
101108

@@ -112,9 +119,7 @@ auto Server::on_document_symbol(proto::DocumentSymbolParams params) -> Result {
112119
proto::DocumentSymbol result;
113120
result.name = std::move(symbol.name);
114121
result.detail = std::move(symbol.detail);
115-
116-
/// FIXME: Add kind map.
117-
result.kind = static_cast<proto::SymbolKind>(symbol.kind.value());
122+
result.kind = proto::kind_map(symbol.kind.kind());
118123
result.range = to_range(symbol.range);
119124
result.selectionRange = to_range(symbol.selectionRange);
120125

@@ -126,7 +131,7 @@ auto Server::on_document_symbol(proto::DocumentSymbolParams params) -> Result {
126131
};
127132

128133
co_return co_await async::submit([&ast, &transform] {
129-
auto symbols = feature::document_symbols(*ast);
134+
auto symbols = feature::document_symbol(*ast);
130135

131136
std::vector<proto::DocumentSymbol> result;
132137
for(auto& symbol: symbols) {
@@ -140,10 +145,12 @@ auto Server::on_document_symbol(proto::DocumentSymbolParams params) -> Result {
140145
auto Server::on_document_link(proto::DocumentLinkParams params) -> Result {
141146
auto path = mapping.to_path(params.textDocument.uri);
142147
auto opening_file = opening_files.get_or_add(path);
143-
auto guard = co_await opening_file->ast_built_lock.try_lock();
148+
auto version = opening_file->version;
144149

150+
auto guard = co_await opening_file->ast_built_lock.try_lock();
145151
auto ast = opening_file->ast;
146-
if(!ast) {
152+
153+
if(opening_file->version != version || !ast) {
147154
co_return json::Value(nullptr);
148155
}
149156

@@ -195,10 +202,12 @@ auto Server::on_document_range_format(proto::DocumentRangeFormattingParams param
195202
async::Task<json::Value> Server::on_folding_range(proto::FoldingRangeParams params) {
196203
auto path = mapping.to_path(params.textDocument.uri);
197204
auto opening_file = opening_files.get_or_add(path);
198-
auto guard = co_await opening_file->ast_built_lock.try_lock();
205+
auto version = opening_file->version;
199206

207+
auto guard = co_await opening_file->ast_built_lock.try_lock();
200208
auto ast = opening_file->ast;
201-
if(!ast) {
209+
210+
if(opening_file->version != version || !ast) {
202211
co_return json::Value(nullptr);
203212
}
204213

@@ -233,10 +242,12 @@ async::Task<json::Value> Server::on_folding_range(proto::FoldingRangeParams para
233242
auto Server::on_semantic_token(proto::SemanticTokensParams params) -> Result {
234243
auto path = mapping.to_path(params.textDocument.uri);
235244
auto opening_file = opening_files.get_or_add(path);
236-
auto guard = co_await opening_file->ast_built_lock.try_lock();
245+
auto version = opening_file->version;
237246

247+
auto guard = co_await opening_file->ast_built_lock.try_lock();
238248
auto ast = opening_file->ast;
239-
if(!ast) {
249+
250+
if(opening_file->version != version || !ast) {
240251
co_return json::Value(nullptr);
241252
}
242253

@@ -249,10 +260,12 @@ auto Server::on_semantic_token(proto::SemanticTokensParams params) -> Result {
249260
auto Server::on_inlay_hint(proto::InlayHintParams params) -> Result {
250261
auto path = mapping.to_path(params.textDocument.uri);
251262
auto opening_file = opening_files.get_or_add(path);
252-
auto guard = co_await opening_file->ast_built_lock.try_lock();
263+
auto version = opening_file->version;
253264

265+
auto guard = co_await opening_file->ast_built_lock.try_lock();
254266
auto ast = opening_file->ast;
255-
if(!ast) {
267+
268+
if(opening_file->version != version || !ast) {
256269
co_return json::Value(nullptr);
257270
}
258271

tests/unit/Feature/DocumentSymbol.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ suite<"DocumentSymbol"> document_symbol = [] {
1515
tester.add_main("main.cpp", code);
1616
tester.compile_with_pch();
1717
expect(that % tester.unit.has_value());
18-
symbols = feature::document_symbols(*tester.unit);
18+
symbols = feature::document_symbol(*tester.unit);
1919
};
2020

2121
auto total_size_wrapper = [](const std::vector<feature::DocumentSymbol>& result) -> size_t {

0 commit comments

Comments
 (0)