Skip to content

Commit 4220773

Browse files
committed
Chore: extract struct CommandOptions.
1 parent 9329e9e commit 4220773

File tree

7 files changed

+100
-111
lines changed

7 files changed

+100
-111
lines changed

include/Compiler/Command.h

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,21 @@
1010

1111
namespace clice {
1212

13+
struct CommandOptions {
14+
/// The file to get command for.
15+
llvm::StringRef file;
16+
17+
/// Attach resource directory to the command.
18+
bool resource_dir = false;
19+
20+
/// Query the compiler driver for additional information, such as system includes and target.
21+
bool query_driver = false;
22+
23+
/// Suppress the warning log if failed to query driver info.
24+
/// Set true in unittests to avoid cluttering test output.
25+
bool suppress_log = false;
26+
};
27+
1328
class CompilationDatabase {
1429
public:
1530
using Self = CompilationDatabase;
@@ -21,18 +36,6 @@ class CompilationDatabase {
2136
Delete,
2237
};
2338

24-
struct QueryDriverErrorKind : refl::Enum<QueryDriverErrorKind> {
25-
enum Kind : std::uint8_t {
26-
NotFoundInPATH,
27-
FailToCreateTempFile,
28-
InvokeDriverFail,
29-
OutputFileNotReadable,
30-
InvalidOutputFormat,
31-
};
32-
33-
using Enum::Enum;
34-
};
35-
3639
struct CommandInfo {
3740
/// TODO: add sysroot or no stdinc command info.
3841
llvm::StringRef dictionary;
@@ -63,10 +66,20 @@ class CompilationDatabase {
6366
};
6467

6568
struct QueryDriverError {
66-
QueryDriverErrorKind kind;
67-
std::string driver;
69+
struct ErrorKind : refl::Enum<ErrorKind> {
70+
enum Kind : std::uint8_t {
71+
NotFoundInPATH,
72+
FailToCreateTempFile,
73+
InvokeDriverFail,
74+
OutputFileNotReadable,
75+
InvalidOutputFormat,
76+
};
77+
78+
using Enum::Enum;
79+
};
80+
81+
ErrorKind kind;
6882
std::string detail;
69-
std::optional<std::string> output_file;
7083
};
7184

7285
CompilationDatabase();
@@ -99,10 +112,7 @@ class CompilationDatabase {
99112
auto load_commands(this Self& self, llvm::StringRef json_content)
100113
-> std::expected<std::vector<UpdateInfo>, std::string>;
101114

102-
auto get_command(this Self& self,
103-
llvm::StringRef file,
104-
bool resource_dir = false,
105-
bool query_driver = false) -> LookupInfo;
115+
auto get_command(this Self& self, CommandOptions options) -> LookupInfo;
106116

107117
private:
108118
/// The memory pool to hold all cstring and command list.
@@ -159,13 +169,7 @@ struct std::formatter<clice::CompilationDatabase::QueryDriverError> :
159169

160170
template <typename FormatContext>
161171
auto format(clice::CompilationDatabase::QueryDriverError& e, FormatContext& ctx) const {
162-
return std::format_to(
163-
ctx.out(),
164-
"QueryDriverError{{ kind: {}, driver: {}, detail: {}, output_file: {} }}",
165-
e.kind.name(),
166-
e.driver,
167-
e.detail,
168-
e.output_file.value_or("<no file>"));
172+
return std::format_to(ctx.out(), "{} {}", e.kind.name(), e.detail);
169173
}
170174
};
171175

include/Test/Tester.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,13 @@ struct Tester {
3636

3737
database.update_command("fake", src_path, command);
3838
params.kind = CompilationUnit::Content;
39-
params.arguments = database.get_command(src_path, true, true).arguments;
39+
40+
CommandOptions options;
41+
options.file = src_path;
42+
options.resource_dir = true;
43+
options.query_driver = true;
44+
options.suppress_log = true;
45+
params.arguments = database.get_command(options).arguments;
4046

4147
for(auto& [file, source]: sources.all_files) {
4248
if(file == src_path) {
@@ -67,7 +73,13 @@ struct Tester {
6773

6874
database.update_command("fake", src_path, command);
6975
params.kind = CompilationUnit::Preamble;
70-
params.arguments = database.get_command(src_path, true, true).arguments;
76+
77+
CommandOptions options;
78+
options.file = src_path;
79+
options.resource_dir = true;
80+
options.query_driver = true;
81+
options.suppress_log = true;
82+
params.arguments = database.get_command(options).arguments;
7183

7284
auto path = fs::createTemporaryFile("clice", "pch");
7385
if(!path) {

src/Compiler/Command.cpp

Lines changed: 15 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -108,25 +108,10 @@ llvm::SmallVector<llvm::StringRef, 4> driver_invocation_argv(llvm::StringRef dri
108108
}
109109

110110
using QueryDriverError = CompilationDatabase::QueryDriverError;
111-
using ErrorKind = CompilationDatabase::QueryDriverErrorKind;
112-
113-
auto unexpected(ErrorKind kind,
114-
llvm::StringRef driver,
115-
std::string&& message,
116-
std::optional<std::string> output_file = std::nullopt)
117-
-> std::expected<CompilationDatabase::DriverInfo, QueryDriverError> {
118-
QueryDriverError err{kind,
119-
driver.str(),
120-
std::forward<std::string>(message),
121-
std::move(output_file)};
122-
return std::unexpected(std::move(err));
123-
};
111+
using ErrorKind = CompilationDatabase::QueryDriverError::ErrorKind;
124112

125-
template <typename T>
126-
auto unexpected(ErrorKind kind, llvm::StringRef driver, const llvm::ErrorOr<T>& error)
127-
-> std::expected<CompilationDatabase::DriverInfo, QueryDriverError> {
128-
QueryDriverError err{kind, driver.str(), std::format("{}", error.getError())};
129-
return std::unexpected(std::move(err));
113+
auto unexpected(ErrorKind kind, std::string message) {
114+
return std::unexpected<QueryDriverError>({kind, std::move(message)});
130115
};
131116

132117
} // namespace
@@ -139,7 +124,7 @@ auto CompilationDatabase::query_driver(this Self& self, llvm::StringRef driver)
139124
if(auto error = fs::real_path(driver, absolute_path)) {
140125
auto result = llvm::sys::findProgramByName(driver);
141126
if(!result) {
142-
return unexpected(ErrorKind::NotFoundInPATH, driver, result);
127+
return unexpected(ErrorKind::NotFoundInPATH, result.getError().message());
143128
}
144129
absolute_path = *result;
145130
}
@@ -156,7 +141,7 @@ auto CompilationDatabase::query_driver(this Self& self, llvm::StringRef driver)
156141

157142
llvm::SmallString<128> output_path;
158143
if(auto error = llvm::sys::fs::createTemporaryFile("system-includes", "clice", output_path)) {
159-
return unexpected(ErrorKind::FailToCreateTempFile, driver, error.message());
144+
return unexpected(ErrorKind::FailToCreateTempFile, error.message());
160145
}
161146

162147
// If we fail to get the driver infomation, keep the output file for user to debug.
@@ -184,12 +169,12 @@ auto CompilationDatabase::query_driver(this Self& self, llvm::StringRef driver)
184169
/*SecondsToWait=*/0,
185170
/*MemoryLimit=*/0,
186171
&message)) {
187-
return unexpected(ErrorKind::InvokeDriverFail, driver, std::move(message));
172+
return unexpected(ErrorKind::InvokeDriverFail, std::move(message));
188173
}
189174

190175
auto file = llvm::MemoryBuffer::getFile(output_path);
191176
if(!file) {
192-
return unexpected(ErrorKind::OutputFileNotReadable, driver, file.getError().message());
177+
return unexpected(ErrorKind::OutputFileNotReadable, file.getError().message());
193178
}
194179

195180
llvm::StringRef content = file.get()->getBuffer();
@@ -235,17 +220,11 @@ auto CompilationDatabase::query_driver(this Self& self, llvm::StringRef driver)
235220
}
236221

237222
if(!found_start_marker) {
238-
return unexpected(ErrorKind::InvalidOutputFormat,
239-
driver,
240-
"Start marker not found...",
241-
output_path.str().str());
223+
return unexpected(ErrorKind::InvalidOutputFormat, "Start marker not found...");
242224
}
243225

244226
if(in_includes_block) {
245-
return unexpected(ErrorKind::InvalidOutputFormat,
246-
driver,
247-
"End marker not found...",
248-
output_path.str().str());
227+
return unexpected(ErrorKind::InvalidOutputFormat, "End marker not found...");
249228
}
250229

251230
// Get driver information success, remove temporary file.
@@ -468,45 +447,10 @@ auto CompilationDatabase::load_commands(this Self& self, llvm::StringRef json_co
468447
return infos;
469448
}
470449

471-
namespace {
472-
473-
/// Show warn and optional hint message for query driver error in log.
474-
void handle_query_driver_error(QueryDriverError error) {
475-
log::warn("Failed to query driver info: {}", error);
476-
477-
llvm::SmallString<256> hint;
478-
llvm::raw_svector_ostream os(hint);
479-
if(error.kind == ErrorKind::NotFoundInPATH) {
480-
os << "Make sure that " << error.driver
481-
<< " has been installed in your PATH, or update the compile_commands.json to use correct driver.";
482-
} else if(error.kind == ErrorKind::InvokeDriverFail) {
483-
os << "The failed invocation command is: " << error.driver;
484-
for(llvm::StringRef arg: driver_invocation_argv(error.driver)) {
485-
os << ' ' << arg;
486-
}
487-
} else if(error.kind == ErrorKind::InvalidOutputFormat) {
488-
os << "Check the output format of output file: " << error.output_file.value_or("<unknown>")
489-
<< ", for GCC/Clang it should be like:\n\n"
490-
<< "Target: <target>\n"
491-
<< "#include <...> search starts here:\n"
492-
<< "<system includes>\n"
493-
<< "End of search list.";
494-
}
495-
496-
if(!hint.empty()) {
497-
log::warn("HINT: {}", hint);
498-
}
499-
}
500-
501-
} // namespace
502-
503-
auto CompilationDatabase::get_command(this Self& self,
504-
llvm::StringRef file,
505-
bool resource_dir,
506-
bool query_driver) -> LookupInfo {
450+
auto CompilationDatabase::get_command(this Self& self, CommandOptions options) -> LookupInfo {
507451
LookupInfo info;
508452

509-
file = self.save_string(file);
453+
llvm::StringRef file = self.save_string(options.file);
510454
auto it = self.command_infos.find(file.data());
511455
if(it != self.command_infos.end()) {
512456
info.dictionary = it->second.dictionary;
@@ -524,7 +468,7 @@ auto CompilationDatabase::get_command(this Self& self,
524468
info.arguments.emplace_back(self.save_string(argument).data());
525469
};
526470

527-
if(query_driver) {
471+
if(options.query_driver) {
528472
llvm::StringRef driver = info.arguments[0];
529473
if(auto driver_info = self.query_driver(driver)) {
530474
append_argument("-nostdlibinc");
@@ -536,14 +480,12 @@ auto CompilationDatabase::get_command(this Self& self,
536480
append_argument("-I");
537481
append_argument(system_header);
538482
}
539-
} else {
540-
/// FIXME: Show log in `handle_query_driver_error` will cause many unsed output in
541-
/// unittest. We should find a way to suppress this output in unittest.
542-
handle_query_driver_error(std::move(driver_info).error());
483+
} else if(!options.suppress_log) {
484+
log::warn("Failed to query driver:{}, error:{}", driver, driver_info.error());
543485
}
544486
}
545487

546-
if(resource_dir) {
488+
if(options.resource_dir) {
547489
append_argument(std::format("-resource-dir={}", fs::resource_dir));
548490
}
549491

src/Server/Document.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,13 @@ async::Task<bool> build_pch_task(CompilationDatabase::LookupInfo& info,
240240
} // namespace
241241

242242
async::Task<bool> Server::build_pch(std::string file, std::string content) {
243+
CommandOptions options;
244+
options.file = file;
245+
options.resource_dir = true;
246+
options.query_driver = true;
247+
auto info = database.get_command(options);
248+
243249
auto bound = compute_preamble_bound(content);
244-
auto info = database.get_command(file, true, true);
245250
auto& open_file = opening_files.get_or_add(file);
246251

247252
/// Check update ...
@@ -294,9 +299,14 @@ async::Task<> Server::build_ast(std::string path, std::string content) {
294299
log::fatal("Expected PCH built at this point");
295300
}
296301

302+
CommandOptions options;
303+
options.file = path;
304+
options.resource_dir = true;
305+
options.query_driver = true;
306+
297307
CompilationParams params;
298308
params.kind = CompilationUnit::Content;
299-
params.arguments = database.get_command(path, true, true).arguments;
309+
params.arguments = database.get_command(options).arguments;
300310
params.add_remapped_file(path, content);
301311
params.pch = {pch->path, pch->preamble.size()};
302312
file->diagnostics->clear();

src/Server/Feature.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,14 @@ auto Server::on_completion(proto::CompletionParams params) -> Result {
2525
auto offset = to_offset(kind, content, params.position);
2626
auto& pch = opening_file->pch;
2727
{
28+
CommandOptions options;
29+
options.file = path;
30+
options.resource_dir = true;
31+
2832
/// Set compilation params ... .
2933
CompilationParams params;
3034
params.kind = CompilationUnit::Completion;
31-
params.arguments = database.get_command(path, true).arguments;
35+
params.arguments = database.get_command(options).arguments;
3236
params.add_remapped_file(path, content);
3337
params.pch = {pch->path, pch->preamble.size()};
3438
params.completion = {path, offset};
@@ -74,10 +78,14 @@ async::Task<json::Value> Server::on_signature_help(proto::SignatureHelpParams pa
7478
auto offset = to_offset(kind, content, params.position);
7579
auto& pch = opening_file->pch;
7680
{
81+
CommandOptions options;
82+
options.file = path;
83+
options.resource_dir = true;
84+
7785
/// Set compilation params ... .
7886
CompilationParams params;
7987
params.kind = CompilationUnit::Completion;
80-
params.arguments = database.get_command(path, true).arguments;
88+
params.arguments = database.get_command(options).arguments;
8189
params.add_remapped_file(path, content);
8290
params.pch = {pch->path, pch->preamble.size()};
8391
params.completion = {path, offset};

src/Server/Indexer.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,12 @@ async::Task<> Indexer::index(CompilationUnit& unit) {
4646
}
4747

4848
async::Task<> Indexer::index(llvm::StringRef file) {
49+
CommandOptions options;
50+
options.file = file;
51+
4952
CompilationParams params;
5053
params.kind = CompilationUnit::Indexing;
51-
params.arguments = database.get_command(file).arguments;
54+
params.arguments = database.get_command(options).arguments;
5255

5356
auto AST = co_await async::submit([&] { return compile(params); });
5457

tests/unit/Compiler/Command.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,13 @@ void parse_and_dump(llvm::StringRef command) {
5757
suite<"Command"> command = [] {
5858
auto expect_strip = [](llvm::StringRef argv, llvm::StringRef result) {
5959
CompilationDatabase database;
60-
database.update_command("fake/", "main.cpp", argv);
61-
expect(that % printArgv(database.get_command("main.cpp").arguments) == result);
60+
llvm::StringRef file = "main.cpp";
61+
database.update_command("fake/", file, argv);
62+
63+
CommandOptions options;
64+
options.file = "main.cpp";
65+
options.suppress_log = true;
66+
expect(that % printArgv(database.get_command(options).arguments) == result);
6267
};
6368

6469
test("GetOptionID") = [] {
@@ -140,8 +145,13 @@ suite<"Command"> command = [] {
140145
database.update_command("fake", "test.cpp", "clang++ -std=c++23 test.cpp"sv);
141146
database.update_command("fake", "test2.cpp", "clang++ -std=c++23 test2.cpp"sv);
142147

143-
auto command1 = database.get_command("test.cpp").arguments;
144-
auto command2 = database.get_command("test2.cpp").arguments;
148+
CommandOptions options;
149+
options.suppress_log = true;
150+
151+
options.file = "test.cpp";
152+
auto command1 = database.get_command(options).arguments;
153+
options.file = "test2.cpp";
154+
auto command2 = database.get_command(options).arguments;
145155
expect(that % command1.size() == 3);
146156
expect(that % command2.size() == 3);
147157

@@ -161,7 +171,7 @@ suite<"Command"> command = [] {
161171
test("QueryDriver") = [] {
162172
#ifdef _GLIBCXX_RELEASE
163173
using namespace std::literals;
164-
using ErrorKind = CompilationDatabase::QueryDriverErrorKind;
174+
using ErrorKind = CompilationDatabase::QueryDriverError::ErrorKind;
165175

166176
CompilationDatabase database;
167177
auto info = database.query_driver("g++");

0 commit comments

Comments
 (0)