diff --git a/clang-tools-extra/clangd/CMakeLists.txt b/clang-tools-extra/clangd/CMakeLists.txt --- a/clang-tools-extra/clangd/CMakeLists.txt +++ b/clang-tools-extra/clangd/CMakeLists.txt @@ -63,6 +63,7 @@ JSONTransport.cpp Logger.cpp PathMapping.cpp + Protobuf.cpp Protocol.cpp Quality.cpp ParsedAST.cpp diff --git a/clang-tools-extra/clangd/Protobuf.h b/clang-tools-extra/clangd/Protobuf.h new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/Protobuf.h @@ -0,0 +1,24 @@ +//===--- Protobuf.h - ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOBUF_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOBUF_H + +#include "clang/AST/Decl.h" + +namespace clang { +namespace clangd { + +/// Checks whether the decl is a private symbol in a header generated by +/// protobuf compiler. +bool isPrivateProtoDecl(const NamedDecl &ND); + +} // namespace clangd +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PROTOBUF_H diff --git a/clang-tools-extra/clangd/Protobuf.cpp b/clang-tools-extra/clangd/Protobuf.cpp new file mode 100644 --- /dev/null +++ b/clang-tools-extra/clangd/Protobuf.cpp @@ -0,0 +1,54 @@ +//===--- Protobuf.cpp -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Protobuf.h" +#include "AST.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/Decl.h" + +namespace clang { +namespace clangd { + +// All proto generated headers should start with this line. +static const char *PROTO_HEADER_COMMENT = + "// Generated by the protocol buffer compiler. DO NOT EDIT!"; + +// 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 = nameLocation(ND, SM); + auto FileName = SM.getFilename(Loc); + if (!FileName.endswith(".proto.h") && !FileName.endswith(".pb.h")) + return false; + auto FID = SM.getFileID(Loc); + // To identify whether a proto header is actually generated by proto compiler, + // we check whether it starts with PROTO_HEADER_COMMENT. + 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) || llvm::any_of(Name, islower); +} + +} // namespace clangd +} // namespace clang diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -13,6 +13,7 @@ #include "CodeCompletionStrings.h" #include "ExpectedTypes.h" #include "Logger.h" +#include "Protobuf.h" #include "SourceCode.h" #include "SymbolLocation.h" #include "URI.h" @@ -70,45 +71,6 @@ return URI::create(AbsolutePath).toString(); } -// 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 = nameLocation(ND, SM); - 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) || llvm::any_of(Name, islower); -} - // We only collect #include paths for symbols that are suitable for global code // completion, except for namespaces since #include path for a namespace is hard // to define.