diff options
Diffstat (limited to 'clang-tools-extra/clangd/index/SymbolCollector.cpp')
-rw-r--r-- | clang-tools-extra/clangd/index/SymbolCollector.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp index 9e9df7fd9d5..6af4a4ead01 100644 --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -89,6 +89,46 @@ llvm::Optional<std::string> toURI(const SourceManager &SM, StringRef Path, return llvm::None; } +// All proto generated headers should start with this line. +static const char *PROTO_HEADER_COMMENT = + "// Generated by the protocol buffer compiler. DO NOT EDIT!"; + +// Checks whether the decl is a private symbol in a header generated by +// protobuf compiler. +// To identify whether a proto header is actually generated by proto compiler, +// we check whether it starts with PROTO_HEADER_COMMENT. +// FIXME: make filtering extensible when there are more use cases for symbol +// filters. +bool isPrivateProtoDecl(const NamedDecl &ND) { + const auto &SM = ND.getASTContext().getSourceManager(); + auto Loc = findNameLoc(&ND); + auto FileName = SM.getFilename(Loc); + if (!FileName.endswith(".proto.h") && !FileName.endswith(".pb.h")) + return false; + auto FID = SM.getFileID(Loc); + // Double check that this is an actual protobuf header. + if (!SM.getBufferData(FID).startswith(PROTO_HEADER_COMMENT)) + return false; + + // ND without identifier can be operators. + if (ND.getIdentifier() == nullptr) + return false; + auto Name = ND.getIdentifier()->getName(); + if (!Name.contains('_')) + return false; + // Nested proto entities (e.g. Message::Nested) have top-level decls + // that shouldn't be used (Message_Nested). Ignore them completely. + // The nested entities are dangling type aliases, we may want to reconsider + // including them in the future. + // For enum constants, SOME_ENUM_CONSTANT is not private and should be + // indexed. Outer_INNER is private. This heuristic relies on naming style, it + // will include OUTER_INNER and exclude some_enum_constant. + // FIXME: the heuristic relies on naming style (i.e. no underscore in + // user-defined names) and can be improved. + return (ND.getKind() != Decl::EnumConstant) || + std::any_of(Name.begin(), Name.end(), islower); +} + bool shouldFilterDecl(const NamedDecl *ND, ASTContext *ASTCtx, const SymbolCollector::Options &Opts) { using namespace clang::ast_matchers; @@ -129,6 +169,9 @@ bool shouldFilterDecl(const NamedDecl *ND, ASTContext *ASTCtx, .empty()) return true; + // Avoid indexing internal symbols in protobuf generated headers. + if (isPrivateProtoDecl(*ND)) + return true; return false; } |