[clangd] Provide a way to disable external index
Users can reset any external index set by previous fragments by putting a `None` for the external block, e.g: ``` Index: External: None ``` Differential Revision: https://reviews.llvm.org/D100106
This commit is contained in:
parent
4cbaaf4a24
commit
63bc9e4435
|
|
@ -70,7 +70,7 @@ struct Config {
|
||||||
enum class BackgroundPolicy { Build, Skip };
|
enum class BackgroundPolicy { Build, Skip };
|
||||||
/// Describes an external index configuration.
|
/// Describes an external index configuration.
|
||||||
struct ExternalIndexSpec {
|
struct ExternalIndexSpec {
|
||||||
enum { File, Server } Kind;
|
enum { None, File, Server } Kind;
|
||||||
/// This is one of:
|
/// This is one of:
|
||||||
/// - Address of a clangd-index-server, in the form of "ip:port".
|
/// - Address of a clangd-index-server, in the form of "ip:port".
|
||||||
/// - Absolute path to an index produced by clangd-indexer.
|
/// - Absolute path to an index produced by clangd-indexer.
|
||||||
|
|
|
||||||
|
|
@ -329,10 +329,11 @@ struct FragmentCompiler {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Make sure exactly one of the Sources is set.
|
// Make sure exactly one of the Sources is set.
|
||||||
unsigned SourceCount =
|
unsigned SourceCount = External.File.hasValue() +
|
||||||
External.File.hasValue() + External.Server.hasValue();
|
External.Server.hasValue() + *External.IsNone;
|
||||||
if (SourceCount != 1) {
|
if (SourceCount != 1) {
|
||||||
diag(Error, "Exactly one of File or Server must be set.", BlockRange);
|
diag(Error, "Exactly one of File, Server or None must be set.",
|
||||||
|
BlockRange);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Config::ExternalIndexSpec Spec;
|
Config::ExternalIndexSpec Spec;
|
||||||
|
|
@ -346,20 +347,29 @@ struct FragmentCompiler {
|
||||||
if (!AbsPath)
|
if (!AbsPath)
|
||||||
return;
|
return;
|
||||||
Spec.Location = std::move(*AbsPath);
|
Spec.Location = std::move(*AbsPath);
|
||||||
|
} else {
|
||||||
|
assert(*External.IsNone);
|
||||||
|
Spec.Kind = Config::ExternalIndexSpec::None;
|
||||||
}
|
}
|
||||||
// Make sure MountPoint is an absolute path with forward slashes.
|
if (Spec.Kind != Config::ExternalIndexSpec::None) {
|
||||||
if (!External.MountPoint)
|
// Make sure MountPoint is an absolute path with forward slashes.
|
||||||
External.MountPoint.emplace(FragmentDirectory);
|
if (!External.MountPoint)
|
||||||
if ((**External.MountPoint).empty()) {
|
External.MountPoint.emplace(FragmentDirectory);
|
||||||
diag(Error, "A mountpoint is required.", BlockRange);
|
if ((**External.MountPoint).empty()) {
|
||||||
return;
|
diag(Error, "A mountpoint is required.", BlockRange);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto AbsPath = makeAbsolute(std::move(*External.MountPoint), "MountPoint",
|
||||||
|
llvm::sys::path::Style::posix);
|
||||||
|
if (!AbsPath)
|
||||||
|
return;
|
||||||
|
Spec.MountPoint = std::move(*AbsPath);
|
||||||
}
|
}
|
||||||
auto AbsPath = makeAbsolute(std::move(*External.MountPoint), "MountPoint",
|
|
||||||
llvm::sys::path::Style::posix);
|
|
||||||
if (!AbsPath)
|
|
||||||
return;
|
|
||||||
Spec.MountPoint = std::move(*AbsPath);
|
|
||||||
Out.Apply.push_back([Spec(std::move(Spec))](const Params &P, Config &C) {
|
Out.Apply.push_back([Spec(std::move(Spec))](const Params &P, Config &C) {
|
||||||
|
if (Spec.Kind == Config::ExternalIndexSpec::None) {
|
||||||
|
C.Index.External.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (P.Path.empty() || !pathStartsWith(Spec.MountPoint, P.Path,
|
if (P.Path.empty() || !pathStartsWith(Spec.MountPoint, P.Path,
|
||||||
llvm::sys::path::Style::posix))
|
llvm::sys::path::Style::posix))
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -173,6 +173,9 @@ struct Fragment {
|
||||||
/// usually prepared using clangd-indexer.
|
/// usually prepared using clangd-indexer.
|
||||||
/// Exactly one source (File/Server) should be configured.
|
/// Exactly one source (File/Server) should be configured.
|
||||||
struct ExternalBlock {
|
struct ExternalBlock {
|
||||||
|
/// Whether the block is explicitly set to `None`. Can be used to clear
|
||||||
|
/// any external index specified before.
|
||||||
|
Located<bool> IsNone = false;
|
||||||
/// Path to an index file generated by clangd-indexer. Relative paths may
|
/// Path to an index file generated by clangd-indexer. Relative paths may
|
||||||
/// be used, if config fragment is associated with a directory.
|
/// be used, if config fragment is associated with a directory.
|
||||||
llvm::Optional<Located<std::string>> File;
|
llvm::Optional<Located<std::string>> File;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#include "llvm/Support/MemoryBuffer.h"
|
#include "llvm/Support/MemoryBuffer.h"
|
||||||
#include "llvm/Support/SourceMgr.h"
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/YAMLParser.h"
|
#include "llvm/Support/YAMLParser.h"
|
||||||
|
#include <string>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
namespace clang {
|
namespace clang {
|
||||||
|
|
@ -149,13 +150,34 @@ private:
|
||||||
[&](Node &N) { F.Background = scalarValue(N, "Background"); });
|
[&](Node &N) { F.Background = scalarValue(N, "Background"); });
|
||||||
Dict.handle("External", [&](Node &N) {
|
Dict.handle("External", [&](Node &N) {
|
||||||
Fragment::IndexBlock::ExternalBlock External;
|
Fragment::IndexBlock::ExternalBlock External;
|
||||||
parse(External, N);
|
// External block can either be a mapping or a scalar value. Dispatch
|
||||||
|
// accordingly.
|
||||||
|
if (N.getType() == Node::NK_Mapping) {
|
||||||
|
parse(External, N);
|
||||||
|
} else if (N.getType() == Node::NK_Scalar ||
|
||||||
|
N.getType() == Node::NK_BlockScalar) {
|
||||||
|
parse(External, scalarValue(N, "External").getValue());
|
||||||
|
} else {
|
||||||
|
error("External must be either a scalar or a mapping.", N);
|
||||||
|
return;
|
||||||
|
}
|
||||||
F.External.emplace(std::move(External));
|
F.External.emplace(std::move(External));
|
||||||
F.External->Range = N.getSourceRange();
|
F.External->Range = N.getSourceRange();
|
||||||
});
|
});
|
||||||
Dict.parse(N);
|
Dict.parse(N);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void parse(Fragment::IndexBlock::ExternalBlock &F,
|
||||||
|
Located<std::string> ExternalVal) {
|
||||||
|
if (!llvm::StringRef(*ExternalVal).equals_lower("none")) {
|
||||||
|
error("Only scalar value supported for External is 'None'",
|
||||||
|
ExternalVal.Range);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
F.IsNone = true;
|
||||||
|
F.IsNone.Range = ExternalVal.Range;
|
||||||
|
}
|
||||||
|
|
||||||
void parse(Fragment::IndexBlock::ExternalBlock &F, Node &N) {
|
void parse(Fragment::IndexBlock::ExternalBlock &F, Node &N) {
|
||||||
DictParser Dict("External", this);
|
DictParser Dict("External", this);
|
||||||
Dict.handle("File", [&](Node &N) { F.File = scalarValue(N, "File"); });
|
Dict.handle("File", [&](Node &N) { F.File = scalarValue(N, "File"); });
|
||||||
|
|
|
||||||
|
|
@ -327,21 +327,31 @@ TEST_F(ConfigCompileTests, ExternalBlockWarnOnMultipleSource) {
|
||||||
#ifdef CLANGD_ENABLE_REMOTE
|
#ifdef CLANGD_ENABLE_REMOTE
|
||||||
EXPECT_THAT(
|
EXPECT_THAT(
|
||||||
Diags.Diagnostics,
|
Diags.Diagnostics,
|
||||||
Contains(AllOf(DiagMessage("Exactly one of File or Server must be set."),
|
Contains(
|
||||||
DiagKind(llvm::SourceMgr::DK_Error))));
|
AllOf(DiagMessage("Exactly one of File, Server or None must be set."),
|
||||||
|
DiagKind(llvm::SourceMgr::DK_Error))));
|
||||||
#else
|
#else
|
||||||
ASSERT_TRUE(Conf.Index.External.hasValue());
|
ASSERT_TRUE(Conf.Index.External.hasValue());
|
||||||
EXPECT_EQ(Conf.Index.External->Kind, Config::ExternalIndexSpec::File);
|
EXPECT_EQ(Conf.Index.External->Kind, Config::ExternalIndexSpec::File);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(ConfigCompileTests, ExternalBlockDisableWithNone) {
|
||||||
|
Fragment::IndexBlock::ExternalBlock External;
|
||||||
|
External.IsNone = true;
|
||||||
|
Frag.Index.External = std::move(External);
|
||||||
|
compileAndApply();
|
||||||
|
EXPECT_FALSE(Conf.Index.External.hasValue());
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(ConfigCompileTests, ExternalBlockErrOnNoSource) {
|
TEST_F(ConfigCompileTests, ExternalBlockErrOnNoSource) {
|
||||||
Frag.Index.External.emplace(Fragment::IndexBlock::ExternalBlock{});
|
Frag.Index.External.emplace(Fragment::IndexBlock::ExternalBlock{});
|
||||||
compileAndApply();
|
compileAndApply();
|
||||||
EXPECT_THAT(
|
EXPECT_THAT(
|
||||||
Diags.Diagnostics,
|
Diags.Diagnostics,
|
||||||
Contains(AllOf(DiagMessage("Exactly one of File or Server must be set."),
|
Contains(
|
||||||
DiagKind(llvm::SourceMgr::DK_Error))));
|
AllOf(DiagMessage("Exactly one of File, Server or None must be set."),
|
||||||
|
DiagKind(llvm::SourceMgr::DK_Error))));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ConfigCompileTests, ExternalBlockDisablesBackgroundIndex) {
|
TEST_F(ConfigCompileTests, ExternalBlockDisablesBackgroundIndex) {
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,23 @@ horrible
|
||||||
ASSERT_THAT(Results, IsEmpty());
|
ASSERT_THAT(Results, IsEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(ParseYAML, ExternalBlockNone) {
|
||||||
|
CapturedDiags Diags;
|
||||||
|
Annotations YAML(R"yaml(
|
||||||
|
Index:
|
||||||
|
External: None
|
||||||
|
)yaml");
|
||||||
|
auto Results =
|
||||||
|
Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
|
||||||
|
ASSERT_THAT(Diags.Diagnostics, IsEmpty());
|
||||||
|
ASSERT_EQ(Results.size(), 1u);
|
||||||
|
ASSERT_TRUE(Results[0].Index.External);
|
||||||
|
EXPECT_FALSE(Results[0].Index.External.getValue()->File.hasValue());
|
||||||
|
EXPECT_FALSE(Results[0].Index.External.getValue()->MountPoint.hasValue());
|
||||||
|
EXPECT_FALSE(Results[0].Index.External.getValue()->Server.hasValue());
|
||||||
|
EXPECT_THAT(*Results[0].Index.External.getValue()->IsNone, testing::Eq(true));
|
||||||
|
}
|
||||||
|
|
||||||
TEST(ParseYAML, ExternalBlock) {
|
TEST(ParseYAML, ExternalBlock) {
|
||||||
CapturedDiags Diags;
|
CapturedDiags Diags;
|
||||||
Annotations YAML(R"yaml(
|
Annotations YAML(R"yaml(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue