diff --git a/src/feature/document_symbols.cpp b/src/feature/document_symbols.cpp index a9ca933b..40804b16 100644 --- a/src/feature/document_symbols.cpp +++ b/src/feature/document_symbols.cpp @@ -111,65 +111,69 @@ class DocumentSymbolCollector : public FilteredASTVisitor*traverse)(decl); - } - - auto* named = llvm::dyn_cast(decl); - if(!named) { - return (this->*traverse)(decl); - } +private: + auto push_symbol(clang::NamedDecl* decl) { + struct Guard { + std::vector* previous; + std::vector** cursor; + + ~Guard() { + if(previous) { + *cursor = previous; + } + } + }; auto [fid, selection_range] = - unit.decompose_range(unit.expansion_location(named->getLocation())); - auto [fid2, range] = unit.decompose_expansion_range(named->getSourceRange()); + unit.decompose_range(unit.expansion_location(decl->getLocation())); + auto [fid2, range] = unit.decompose_expansion_range(decl->getSourceRange()); if(fid != fid2 || fid != unit.interested_file() || !selection_range.valid() || !range.valid()) { - return true; + return Guard{nullptr, nullptr}; } auto* previous = result.cursor; auto& symbol = result.cursor->emplace_back(); symbol.kind = SymbolKind::from(decl); - symbol.name = ast::display_name_of(named); - symbol.detail = symbol_detail(unit.context(), *named); + symbol.name = ast::display_name_of(decl); + symbol.detail = symbol_detail(unit.context(), *decl); symbol.selection_range = selection_range; symbol.range = range; result.cursor = &symbol.children; - auto ok = (this->*traverse)(decl); - result.cursor = previous; - return ok; + return Guard{previous, &result.cursor}; + } + +public: +#define TRAVERSE_SYMBOL_DECL(type) \ + bool Traverse##type##Decl(clang::type##Decl* decl) { \ + auto guard = this->push_symbol(decl); \ + return Base::Traverse##type##Decl(decl); \ } + TRAVERSE_SYMBOL_DECL(Namespace); + TRAVERSE_SYMBOL_DECL(Enum); + TRAVERSE_SYMBOL_DECL(EnumConstant); + TRAVERSE_SYMBOL_DECL(Function); + TRAVERSE_SYMBOL_DECL(CXXMethod); + TRAVERSE_SYMBOL_DECL(CXXConstructor); + TRAVERSE_SYMBOL_DECL(CXXDestructor); + TRAVERSE_SYMBOL_DECL(CXXConversion); + TRAVERSE_SYMBOL_DECL(CXXDeductionGuide); + TRAVERSE_SYMBOL_DECL(Record); + TRAVERSE_SYMBOL_DECL(CXXRecord); + TRAVERSE_SYMBOL_DECL(Field); + TRAVERSE_SYMBOL_DECL(Var); + TRAVERSE_SYMBOL_DECL(Binding); + TRAVERSE_SYMBOL_DECL(Concept); + +#undef TRAVERSE_SYMBOL_DECL + auto collect() -> std::vector { TraverseDecl(unit.tu()); return std::move(result.symbols); } -private: - static bool is_interested(clang::Decl* decl) { - switch(decl->getKind()) { - case clang::Decl::Namespace: - case clang::Decl::Enum: - case clang::Decl::EnumConstant: - case clang::Decl::Function: - case clang::Decl::CXXMethod: - case clang::Decl::CXXConstructor: - case clang::Decl::CXXDestructor: - case clang::Decl::CXXConversion: - case clang::Decl::CXXDeductionGuide: - case clang::Decl::Record: - case clang::Decl::CXXRecord: - case clang::Decl::Field: - case clang::Decl::Var: - case clang::Decl::Binding: - case clang::Decl::Concept: return true; - default: return false; - } - } - private: SymbolFrame result; }; diff --git a/src/semantic/filtered_ast_visitor.h b/src/semantic/filtered_ast_visitor.h index 2f09035a..81c83ff6 100644 --- a/src/semantic/filtered_ast_visitor.h +++ b/src/semantic/filtered_ast_visitor.h @@ -33,6 +33,8 @@ class FilteredASTVisitor : public clang::RecursiveASTVisitor { return true; } + /// Clang doesn't visit implicit declarations and + /// implicit template instantiations by default. if(llvm::isa(decl)) { if(interested_only) { for(auto top: unit.top_level_decls()) { @@ -46,34 +48,7 @@ class FilteredASTVisitor : public clang::RecursiveASTVisitor { return Base::TraverseDecl(decl); } - if(decl->isImplicit()) { - return true; - } - - /// We don't want to visit implicit instantiation. - if(auto SD = llvm::dyn_cast(decl)) { - if(SD->getSpecializationKind() == clang::TSK_ImplicitInstantiation) { - return true; - } - } - - if(auto SD = llvm::dyn_cast(decl)) { - if(SD->getTemplateSpecializationKind() == clang::TSK_ImplicitInstantiation) { - return true; - } - } - - if(auto SD = llvm::dyn_cast(decl)) { - if(SD->getSpecializationKind() == clang::TSK_ImplicitInstantiation) { - return true; - } - } - - if constexpr(requires { getDerived().on_traverse_decl(decl, &Base::TraverseDecl); }) { - return getDerived().on_traverse_decl(decl, &Base::TraverseDecl); - } else { - return Base::TraverseDecl(decl); - } + return Base::TraverseDecl(decl); } bool TraverseStmt(clang::Stmt* stmt) { diff --git a/src/semantic/semantic_visitor.h b/src/semantic/semantic_visitor.h index 74729195..87b04b03 100644 --- a/src/semantic/semantic_visitor.h +++ b/src/semantic/semantic_visitor.h @@ -1,5 +1,6 @@ #pragma once +#include "compile/directive.h" #include "semantic/ast_utility.h" #include "semantic/filtered_ast_visitor.h" #include "semantic/relation_kind.h" @@ -107,28 +108,13 @@ class SemanticVisitor : public FilteredASTVisitor> { } void run() { - if(Base::interested_only) { - for(auto decl: unit.top_level_decls()) { - Base::TraverseDecl(decl); - } - } else { - Base::TraverseAST(unit.context()); - } + Base::TraverseAST(unit.context()); for(auto directive: unit.directives()) { for(auto macro: directive.second.macros) { - switch(macro.kind) { - case MacroRef::Kind::Def: { - handleMacroOccurrence(macro.macro, RelationKind::Definition, macro.loc); - break; - } - - case MacroRef::Kind::Ref: - case MacroRef::Kind::Undef: { - handleMacroOccurrence(macro.macro, RelationKind::Reference, macro.loc); - break; - } - } + auto kind = macro.kind == MacroRef::Kind::Def ? RelationKind::Definition + : RelationKind::Reference; + handleMacroOccurrence(macro.macro, kind, macro.loc); } } }