
Reverts llvm/llvm-project#153756 It leads to new build bot failure. https://lab.llvm.org/buildbot/#/builders/145/builds/9200 ``` BUILD FAILED: failed build (failure) Step 5 (build-unified-tree) failure: build (failure) ... 254.983 [140/55/1504] Building CXX object tools/clang/tools/extra/clangd/tool/CMakeFiles/obj.clangdMain.dir/ClangdMain.cpp.o FAILED: tools/clang/tools/extra/clangd/tool/CMakeFiles/obj.clangdMain.dir/ClangdMain.cpp.o ccache /home/buildbots/llvm-external-buildbots/clang.19.1.7/bin/clang++ --gcc-toolchain=/gcc-toolchain/usr -DGTEST_HAS_RTTI=0 -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/build/tools/clang/tools/extra/clangd/tool -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/tool -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/../include-cleaner/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/build/tools/clang/tools/extra/clangd/../clang-tidy -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang- rhel-test/clang-ppc64le-rhel/build/tools/clang/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/build/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/llvm/include -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd -I/home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/build/tools/clang/tools/extra/clangd -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe -unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -fno-common -Woverloaded-virtual -Wno-nested-anon-types -O3 -DNDEBUG -std=c++17 -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/clang/tools/extra/clangd/tool/CMakeFiles/obj.clangdMain.dir/ClangdMain.cpp.o -MF tools/clang/tools/extra/clangd/tool/CMakeFiles/obj.clangdMain.dir/ClangdMain.cpp.o.d -o tools/clang/tools/extra/clangd/tool/CMakeFiles/obj.clangdMain.dir/ClangdMain.cpp.o -c /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/tool/ClangdMain.cpp In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/tool/ClangdMain.cpp:10: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/ClangdLSPServer.h:12: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/ClangdServer.h:12: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/CodeComplete.h:18: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/ASTSignals.h:12: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/ParsedAST.h:23: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/CollectMacros.h:12: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/Protocol.h:26: In file included from /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/URI.h:14: /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/llvm/include/llvm/Support/Registry.h:110:47: error: instantiation of variable 'llvm::Registry<clang::clangd::FeatureModule>::Head' required here, but no definition is available [-Werror,-Wundefined-var-template] 110 | static iterator begin() { return iterator(Head); } | ^ /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/llvm/include/llvm/Support/Registry.h:114:25: note: in instantiation of member function 'llvm::Registry<clang::clangd::FeatureModule>::begin' requested here 114 | return make_range(begin(), end()); | ^ /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/clang-tools-extra/clangd/tool/ClangdMain.cpp:1021:64: note: in instantiation of member function 'llvm::Registry<clang::clangd::FeatureModule>::entries' requested here 1021 | for (FeatureModuleRegistry::entry E : FeatureModuleRegistry::entries()) { | ^ /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/llvm/include/llvm/Support/Registry.h:61:18: note: forward declaration of template entity is here 61 | static node *Head; | ^ /home/buildbots/llvm-external-buildbots/workers/ppc64le-clang-rhel-test/clang-ppc64le-rhel/llvm-project/llvm/include/llvm/Support/Registry.h:110:47: note: add an explicit instantiation declaration to suppress this warning if 'llvm::Registry<clang::clangd::FeatureModule>::Head' is explicitly instantiated in another translation unit 110 | static iterator begin() { return iterator(Head); } | ^ 1 error generated. ``` I need some time to fix this in a correct way
191 lines
7.9 KiB
C++
191 lines
7.9 KiB
C++
//===--- FeatureModule.h - Plugging features into clangd ----------*-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_FEATUREMODULE_H
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FEATUREMODULE_H
|
|
|
|
#include "support/Function.h"
|
|
#include "support/Threading.h"
|
|
#include "clang/Basic/Diagnostic.h"
|
|
#include "llvm/ADT/FunctionExtras.h"
|
|
#include "llvm/Support/Compiler.h"
|
|
#include "llvm/Support/JSON.h"
|
|
#include <memory>
|
|
#include <optional>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
namespace clang {
|
|
class CompilerInstance;
|
|
namespace clangd {
|
|
struct Diag;
|
|
class LSPBinder;
|
|
class SymbolIndex;
|
|
class ThreadsafeFS;
|
|
class TUScheduler;
|
|
class Tweak;
|
|
|
|
/// A FeatureModule contributes a vertical feature to clangd.
|
|
///
|
|
/// The lifetime of a module is roughly:
|
|
/// - feature modules are created before the LSP server, in ClangdMain.cpp
|
|
/// - these modules are then passed to ClangdLSPServer in a FeatureModuleSet
|
|
/// - initializeLSP() is called when the editor calls initialize.
|
|
// - initialize() is then called by ClangdServer as it is constructed.
|
|
/// - module hooks can be called by the server at this point.
|
|
/// Server facilities (scheduler etc) are available.
|
|
/// - ClangdServer will not be destroyed until all the requests are done.
|
|
/// FIXME: Block server shutdown until all the modules are idle.
|
|
/// - When shutting down, ClangdServer will wait for all requests to
|
|
/// finish, call stop(), and then blockUntilIdle().
|
|
/// - feature modules will be destroyed after ClangdLSPServer is destroyed.
|
|
///
|
|
/// FeatureModules are not threadsafe in general. A module's entrypoints are:
|
|
/// - method handlers registered in initializeLSP()
|
|
/// - public methods called directly via ClangdServer.featureModule<T>()->...
|
|
/// - specific overridable "hook" methods inherited from FeatureModule
|
|
/// Unless otherwise specified, these are only called on the main thread.
|
|
///
|
|
/// Conventionally, standard feature modules live in the `clangd` namespace,
|
|
/// and other exposed details live in a sub-namespace.
|
|
class FeatureModule {
|
|
public:
|
|
virtual ~FeatureModule() {
|
|
/// Perform shutdown sequence on destruction in case the ClangdServer was
|
|
/// never initialized. Usually redundant, but shutdown is idempotent.
|
|
stop();
|
|
blockUntilIdle(Deadline::infinity());
|
|
}
|
|
|
|
/// Called by the server to connect this feature module to LSP.
|
|
/// The module should register the methods/notifications/commands it handles,
|
|
/// and update the server capabilities to advertise them.
|
|
///
|
|
/// This is only called if the module is running in ClangdLSPServer!
|
|
/// FeatureModules with a public interface should work without LSP bindings.
|
|
virtual void initializeLSP(LSPBinder &Bind,
|
|
const llvm::json::Object &ClientCaps,
|
|
llvm::json::Object &ServerCaps) {}
|
|
|
|
/// Shared server facilities needed by the module to get its work done.
|
|
struct Facilities {
|
|
TUScheduler &Scheduler;
|
|
const SymbolIndex *Index;
|
|
const ThreadsafeFS &FS;
|
|
};
|
|
/// Called by the server to prepare this module for use.
|
|
void initialize(const Facilities &F);
|
|
|
|
/// Requests that the module cancel background work and go idle soon.
|
|
/// Does not block, the caller will call blockUntilIdle() instead.
|
|
/// After a module is stop()ed, it should not receive any more requests.
|
|
/// Called by the server when shutting down.
|
|
/// May be called multiple times, should be idempotent.
|
|
virtual void stop() {}
|
|
|
|
/// Waits until the module is idle (no background work) or a deadline expires.
|
|
/// In general all modules should eventually go idle, though it may take a
|
|
/// long time (e.g. background indexing).
|
|
/// FeatureModules should go idle quickly if stop() has been called.
|
|
/// Called by the server when shutting down, and also by tests.
|
|
virtual bool blockUntilIdle(Deadline) { return true; }
|
|
|
|
/// Tweaks implemented by this module. Can be called asynchronously when
|
|
/// enumerating or applying code actions.
|
|
virtual void contributeTweaks(std::vector<std::unique_ptr<Tweak>> &Out) {}
|
|
|
|
/// Extension point that allows modules to observe and modify an AST build.
|
|
/// One instance is created each time clangd produces a ParsedAST or
|
|
/// PrecompiledPreamble. For a given instance, lifecycle methods are always
|
|
/// called on a single thread.
|
|
struct ASTListener {
|
|
/// Listeners are destroyed once the AST is built.
|
|
virtual ~ASTListener() = default;
|
|
|
|
/// Called before every AST build, both for main file and preamble. The call
|
|
/// happens immediately before FrontendAction::Execute(), with Preprocessor
|
|
/// set up already and after BeginSourceFile() on main file was called.
|
|
virtual void beforeExecute(CompilerInstance &CI) {}
|
|
|
|
/// Called everytime a diagnostic is encountered. Modules can use this
|
|
/// modify the final diagnostic, or store some information to surface code
|
|
/// actions later on.
|
|
virtual void sawDiagnostic(const clang::Diagnostic &, clangd::Diag &) {}
|
|
};
|
|
/// Can be called asynchronously before building an AST.
|
|
virtual std::unique_ptr<ASTListener> astListeners() { return nullptr; }
|
|
|
|
protected:
|
|
/// Accessors for modules to access shared server facilities they depend on.
|
|
Facilities &facilities();
|
|
/// The scheduler is used to run tasks on worker threads and access ASTs.
|
|
TUScheduler &scheduler() { return facilities().Scheduler; }
|
|
/// The index is used to get information about the whole codebase.
|
|
const SymbolIndex *index() { return facilities().Index; }
|
|
/// The filesystem is used to read source files on disk.
|
|
const ThreadsafeFS &fs() { return facilities().FS; }
|
|
|
|
/// Types of function objects that feature modules use for outgoing calls.
|
|
/// (Bound throuh LSPBinder, made available here for convenience).
|
|
template <typename P>
|
|
using OutgoingNotification = llvm::unique_function<void(const P &)>;
|
|
template <typename P, typename R>
|
|
using OutgoingMethod = llvm::unique_function<void(const P &, Callback<R>)>;
|
|
|
|
private:
|
|
std::optional<Facilities> Fac;
|
|
};
|
|
|
|
/// A FeatureModuleSet is a collection of feature modules installed in clangd.
|
|
///
|
|
/// Modules can be looked up by type, or used via the FeatureModule interface.
|
|
/// This allows individual modules to expose a public API.
|
|
/// For this reason, there can be only one feature module of each type.
|
|
///
|
|
/// The set owns the modules. It is itself owned by main, not ClangdServer.
|
|
class FeatureModuleSet {
|
|
std::vector<std::unique_ptr<FeatureModule>> Modules;
|
|
llvm::DenseMap<void *, FeatureModule *> Map;
|
|
|
|
template <typename Mod> struct ID {
|
|
static_assert(std::is_base_of<FeatureModule, Mod>::value &&
|
|
std::is_final<Mod>::value,
|
|
"Modules must be final classes derived from clangd::Module");
|
|
static int Key;
|
|
};
|
|
|
|
bool addImpl(void *Key, std::unique_ptr<FeatureModule>, const char *Source);
|
|
|
|
public:
|
|
FeatureModuleSet() = default;
|
|
|
|
using iterator = llvm::pointee_iterator<decltype(Modules)::iterator>;
|
|
using const_iterator =
|
|
llvm::pointee_iterator<decltype(Modules)::const_iterator>;
|
|
iterator begin() { return iterator(Modules.begin()); }
|
|
iterator end() { return iterator(Modules.end()); }
|
|
const_iterator begin() const { return const_iterator(Modules.begin()); }
|
|
const_iterator end() const { return const_iterator(Modules.end()); }
|
|
|
|
template <typename Mod> bool add(std::unique_ptr<Mod> M) {
|
|
return addImpl(&ID<Mod>::Key, std::move(M), LLVM_PRETTY_FUNCTION);
|
|
}
|
|
template <typename Mod> Mod *get() {
|
|
return static_cast<Mod *>(Map.lookup(&ID<Mod>::Key));
|
|
}
|
|
template <typename Mod> const Mod *get() const {
|
|
return const_cast<FeatureModuleSet *>(this)->get<Mod>();
|
|
}
|
|
};
|
|
|
|
template <typename Mod> int FeatureModuleSet::ID<Mod>::Key;
|
|
|
|
} // namespace clangd
|
|
} // namespace clang
|
|
#endif
|