mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-24 02:46:05 +00:00
Revert rL359778 : [clangd] Fix code completion of macros defined in the preamble region of the main file.
Summary: This is a tricky case (we baked the assumption that symbols come from the preamble xor mainfile pretty deeply) and the fix is a bit of a hack: We look at the code to guess the macro names, and deserialize them from the preamble "by hand". Reviewers: ilya-biryukov Subscribers: ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D60937 ........ Fix buildbots http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-ubuntu-fast/builds/47684/ llvm-svn: 359796
This commit is contained in:
parent
5c4f031d71
commit
73c44e45ec
@ -20,8 +20,6 @@
|
||||
#include "index/Index.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/TokenKinds.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/CompilerInvocation.h"
|
||||
#include "clang/Frontend/FrontendActions.h"
|
||||
@ -96,36 +94,6 @@ private:
|
||||
std::vector<Decl *> TopLevelDecls;
|
||||
};
|
||||
|
||||
class CollectMainFileMacros : public PPCallbacks {
|
||||
public:
|
||||
explicit CollectMainFileMacros(const SourceManager &SM,
|
||||
std::vector<std::string> *Out)
|
||||
: SM(SM), Out(Out) {}
|
||||
|
||||
void FileChanged(SourceLocation Loc, FileChangeReason,
|
||||
SrcMgr::CharacteristicKind, FileID Prev) {
|
||||
InMainFile = SM.isWrittenInMainFile(Loc);
|
||||
}
|
||||
|
||||
void MacroDefined(const Token &MacroName, const MacroDirective *MD) {
|
||||
assert(MacroName.is(tok::identifier));
|
||||
if (InMainFile)
|
||||
MainFileMacros.insert(MacroName.getIdentifierInfo()->getName());
|
||||
}
|
||||
|
||||
void EndOfMainFile() {
|
||||
for (const auto& Entry : MainFileMacros)
|
||||
Out->push_back(Entry.getKey());
|
||||
llvm::sort(*Out);
|
||||
}
|
||||
|
||||
private:
|
||||
const SourceManager &SM;
|
||||
bool InMainFile = true;
|
||||
llvm::StringSet<> MainFileMacros;
|
||||
std::vector<std::string> *Out;
|
||||
};
|
||||
|
||||
class CppFilePreambleCallbacks : public PreambleCallbacks {
|
||||
public:
|
||||
CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback)
|
||||
@ -135,10 +103,6 @@ public:
|
||||
|
||||
IncludeStructure takeIncludes() { return std::move(Includes); }
|
||||
|
||||
std::vector<std::string> takeMainFileMacros() {
|
||||
return std::move(MainFileMacros);
|
||||
}
|
||||
|
||||
CanonicalIncludes takeCanonicalIncludes() { return std::move(CanonIncludes); }
|
||||
|
||||
void AfterExecute(CompilerInstance &CI) override {
|
||||
@ -154,9 +118,7 @@ public:
|
||||
|
||||
std::unique_ptr<PPCallbacks> createPPCallbacks() override {
|
||||
assert(SourceMgr && "SourceMgr must be set at this point");
|
||||
return llvm::make_unique<PPChainedCallbacks>(
|
||||
collectIncludeStructureCallback(*SourceMgr, &Includes),
|
||||
llvm::make_unique<CollectMainFileMacros>(*SourceMgr, &MainFileMacros));
|
||||
return collectIncludeStructureCallback(*SourceMgr, &Includes);
|
||||
}
|
||||
|
||||
CommentHandler *getCommentHandler() override {
|
||||
@ -169,7 +131,6 @@ private:
|
||||
PreambleParsedCallback ParsedCallback;
|
||||
IncludeStructure Includes;
|
||||
CanonicalIncludes CanonIncludes;
|
||||
std::vector<std::string> MainFileMacros;
|
||||
std::unique_ptr<CommentHandler> IWYUHandler = nullptr;
|
||||
SourceManager *SourceMgr = nullptr;
|
||||
};
|
||||
@ -498,13 +459,11 @@ const CanonicalIncludes &ParsedAST::getCanonicalIncludes() const {
|
||||
|
||||
PreambleData::PreambleData(PrecompiledPreamble Preamble,
|
||||
std::vector<Diag> Diags, IncludeStructure Includes,
|
||||
std::vector<std::string> MainFileMacros,
|
||||
std::unique_ptr<PreambleFileStatusCache> StatCache,
|
||||
CanonicalIncludes CanonIncludes)
|
||||
: Preamble(std::move(Preamble)), Diags(std::move(Diags)),
|
||||
Includes(std::move(Includes)), MainFileMacros(std::move(MainFileMacros)),
|
||||
StatCache(std::move(StatCache)), CanonIncludes(std::move(CanonIncludes)) {
|
||||
}
|
||||
Includes(std::move(Includes)), StatCache(std::move(StatCache)),
|
||||
CanonIncludes(std::move(CanonIncludes)) {}
|
||||
|
||||
ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble,
|
||||
std::unique_ptr<CompilerInstance> Clang,
|
||||
@ -583,8 +542,7 @@ buildPreamble(PathRef FileName, CompilerInvocation &CI,
|
||||
std::vector<Diag> Diags = PreambleDiagnostics.take();
|
||||
return std::make_shared<PreambleData>(
|
||||
std::move(*BuiltPreamble), std::move(Diags),
|
||||
SerializedDeclsCollector.takeIncludes(),
|
||||
SerializedDeclsCollector.takeMainFileMacros(), std::move(StatCache),
|
||||
SerializedDeclsCollector.takeIncludes(), std::move(StatCache),
|
||||
SerializedDeclsCollector.takeCanonicalIncludes());
|
||||
} else {
|
||||
elog("Could not build a preamble for file {0}", FileName);
|
||||
|
@ -48,7 +48,6 @@ namespace clangd {
|
||||
struct PreambleData {
|
||||
PreambleData(PrecompiledPreamble Preamble, std::vector<Diag> Diags,
|
||||
IncludeStructure Includes,
|
||||
std::vector<std::string> MainFileMacros,
|
||||
std::unique_ptr<PreambleFileStatusCache> StatCache,
|
||||
CanonicalIncludes CanonIncludes);
|
||||
|
||||
@ -58,10 +57,6 @@ struct PreambleData {
|
||||
// Processes like code completions and go-to-definitions will need #include
|
||||
// information, and their compile action skips preamble range.
|
||||
IncludeStructure Includes;
|
||||
// Macros defined in the preamble section of the main file.
|
||||
// Users care about headers vs main-file, not preamble vs non-preamble.
|
||||
// These should be treated as main-file entities e.g. for code completion.
|
||||
std::vector<std::string> MainFileMacros;
|
||||
// Cache of FS operations performed when building the preamble.
|
||||
// When reusing a preamble, this cache can be consumed to save IO.
|
||||
std::unique_ptr<PreambleFileStatusCache> StatCache;
|
||||
|
@ -44,8 +44,6 @@
|
||||
#include "clang/Format/Format.h"
|
||||
#include "clang/Frontend/CompilerInstance.h"
|
||||
#include "clang/Frontend/FrontendActions.h"
|
||||
#include "clang/Lex/ExternalPreprocessorSource.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "clang/Lex/PreprocessorOptions.h"
|
||||
#include "clang/Sema/CodeCompleteConsumer.h"
|
||||
#include "clang/Sema/DeclSpec.h"
|
||||
@ -1019,23 +1017,6 @@ struct SemaCompleteInput {
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS;
|
||||
};
|
||||
|
||||
void loadMainFilePreambleMacros(const Preprocessor &PP,
|
||||
const PreambleData &Preamble) {
|
||||
// The ExternalPreprocessorSource has our macros, if we know where to look.
|
||||
// We can read all the macros using PreambleMacros->ReadDefinedMacros(),
|
||||
// but this includes transitively included files, so may deserialize a lot.
|
||||
ExternalPreprocessorSource *PreambleMacros = PP.getExternalSource();
|
||||
// As we have the names of the macros, we can look up their IdentifierInfo
|
||||
// and then use this to load just the macros we want.
|
||||
IdentifierInfoLookup *PreambleIdentifiers =
|
||||
PP.getIdentifierTable().getExternalIdentifierLookup();
|
||||
if (!PreambleIdentifiers || !PreambleMacros)
|
||||
return;
|
||||
for (const auto& MacroName : Preamble.MainFileMacros)
|
||||
if (auto *II = PreambleIdentifiers->get(MacroName))
|
||||
PreambleMacros->updateOutOfDateIdentifier(*II);
|
||||
}
|
||||
|
||||
// Invokes Sema code completion on a file.
|
||||
// If \p Includes is set, it will be updated based on the compiler invocation.
|
||||
bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
|
||||
@ -1077,9 +1058,9 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
|
||||
// However, if we're completing *inside* the preamble section of the draft,
|
||||
// overriding the preamble will break sema completion. Fortunately we can just
|
||||
// skip all includes in this case; these completions are really simple.
|
||||
PreambleBounds PreambleRegion =
|
||||
ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0);
|
||||
bool CompletingInPreamble = PreambleRegion.Size > Input.Offset;
|
||||
bool CompletingInPreamble =
|
||||
ComputePreambleBounds(*CI->getLangOpts(), ContentsBuffer.get(), 0).Size >
|
||||
Input.Offset;
|
||||
// NOTE: we must call BeginSourceFile after prepareCompilerInstance. Otherwise
|
||||
// the remapped buffers do not get freed.
|
||||
IgnoreDiagnostics DummyDiagsConsumer;
|
||||
@ -1097,14 +1078,6 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
|
||||
Input.FileName);
|
||||
return false;
|
||||
}
|
||||
// Macros can be defined within the preamble region of the main file.
|
||||
// They don't fall nicely into our index/Sema dichotomy:
|
||||
// - they're not indexed for completion (they're not available across files)
|
||||
// - but Sema code complete won't see them: as part of the preamble, they're
|
||||
// deserialized only when mentioned.
|
||||
// Force them to be deserialized so SemaCodeComplete sees them.
|
||||
if (Input.Preamble)
|
||||
loadMainFilePreambleMacros(Clang->getPreprocessor(), *Input.Preamble);
|
||||
if (Includes)
|
||||
Clang->getPreprocessor().addPPCallbacks(
|
||||
collectIncludeStructureCallback(Clang->getSourceManager(), Includes));
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/Index/IndexSymbol.h"
|
||||
#include "clang/Index/IndexingAction.h"
|
||||
#include "clang/Index/USRGeneration.h"
|
||||
#include "clang/Lex/Preprocessor.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
|
@ -2073,28 +2073,19 @@ TEST(CompletionTest, MergeMacrosFromIndexAndSema) {
|
||||
UnorderedElementsAre(Named("Clangd_Macro_Test")));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, MacroFromPreamble) {
|
||||
MockFSProvider FS;
|
||||
MockCompilationDatabase CDB;
|
||||
std::string FooHeader = testPath("foo.h");
|
||||
FS.Files[FooHeader] = "#define CLANGD_PREAMBLE_HEADER x\n";
|
||||
IgnoreDiagnostics DiagConsumer;
|
||||
ClangdServer Server(CDB, FS, DiagConsumer, ClangdServer::optsForTest());
|
||||
TEST(CompletionTest, NoMacroFromPreambleIfIndexIsSet) {
|
||||
auto Results = completions(
|
||||
R"cpp(#include "foo.h"
|
||||
#define CLANGD_PREAMBLE_MAIN x
|
||||
R"cpp(#define CLANGD_PREAMBLE x
|
||||
|
||||
int x = 0;
|
||||
#define CLANGD_MAIN x
|
||||
void f() { CLANGD_^ }
|
||||
)cpp",
|
||||
{func("CLANGD_INDEX")});
|
||||
// We should get results from the main file, including the preamble section.
|
||||
// However no results from included files (the index should cover them).
|
||||
EXPECT_THAT(Results.Completions,
|
||||
UnorderedElementsAre(Named("CLANGD_PREAMBLE_MAIN"),
|
||||
Named("CLANGD_MAIN"),
|
||||
Named("CLANGD_INDEX")));
|
||||
// Index is overriden in code completion options, so the preamble symbol is
|
||||
// not seen.
|
||||
EXPECT_THAT(Results.Completions, UnorderedElementsAre(Named("CLANGD_MAIN"),
|
||||
Named("CLANGD_INDEX")));
|
||||
}
|
||||
|
||||
TEST(CompletionTest, DeprecatedResults) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user