mirror of
https://github.com/MaskRay/ccls.git
synced 2025-06-07 16:54:54 +00:00
improvge and fix UB of the use of log
https://github.com/MaskRay/ccls/blob/master/src/main.cc#L90 is not relyable because `1` and `2` are out of range of `enum Verbosity`. According to CWG 1766: > A value of integral or enumeration type can be explicitly converted to an enumeration type. The value is unchanged if the original value is within the range of the enumeration values (10.2 [dcl.enum]). Otherwise, the resulting value is unspecified (and might not be in that range) behavior is undefined. so, stuff like LOG_V(1) and LOG_V(2) are UB. The solution is either: Message(Verbosity verbosity, const char* file, int line); -> Message(int verbosity, const char* file, int line); or ```c++ enum Verbosity { Verbosity_FATAL = -3, Verbosity_ERROR = -2, Verbosity_WARNING = -1, Verbosity_INFO = 0, // more level... }; ``` IMO the latter is better option. This pr also replace macros inside log.hh with short functions and replace `enum Verbosity` with `enum class Verbosity`
This commit is contained in:
parent
b7d9ced086
commit
c0ef47d5e0
@ -37,6 +37,7 @@ limitations under the License.
|
|||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
@ -525,7 +526,8 @@ public:
|
|||||||
}
|
}
|
||||||
auto i = name.find(short_name);
|
auto i = name.find(short_name);
|
||||||
if (short_name.size())
|
if (short_name.size())
|
||||||
while (i != std::string::npos && ((i && isIdentifierBody(name[i - 1])) ||
|
while (i != std::string::npos &&
|
||||||
|
((i && isIdentifierBody(name[i - 1])) ||
|
||||||
isIdentifierBody(name[i + short_name.size()])))
|
isIdentifierBody(name[i + short_name.size()])))
|
||||||
i = name.find(short_name, i + short_name.size());
|
i = name.find(short_name, i + short_name.size());
|
||||||
if (i == std::string::npos) {
|
if (i == std::string::npos) {
|
||||||
@ -794,9 +796,9 @@ public:
|
|||||||
switch (kind) {
|
switch (kind) {
|
||||||
case Kind::Invalid:
|
case Kind::Invalid:
|
||||||
if (ls_kind == SymbolKind::Unknown)
|
if (ls_kind == SymbolKind::Unknown)
|
||||||
LOG_S(INFO) << "Unhandled " << int(D->getKind()) << " "
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
<< info->qualified << " in " << db->path << ":"
|
Log(v, "Unhandled ", int(D->getKind()), " ", info->qualified, " in ",
|
||||||
<< (loc.start.line + 1) << ":" << (loc.start.column + 1);
|
db->path, ":", (loc.start.line + 1), ":", (loc.start.column + 1));
|
||||||
return true;
|
return true;
|
||||||
case Kind::File:
|
case Kind::File:
|
||||||
return true;
|
return true;
|
||||||
@ -952,12 +954,14 @@ public:
|
|||||||
if (auto *RD = dyn_cast<RecordDecl>(D)) {
|
if (auto *RD = dyn_cast<RecordDecl>(D)) {
|
||||||
if (type->def.detailed_name[0] == '\0' && info->short_name.empty()) {
|
if (type->def.detailed_name[0] == '\0' && info->short_name.empty()) {
|
||||||
StringRef Tag;
|
StringRef Tag;
|
||||||
|
// clang-format off
|
||||||
switch (RD->getTagKind()) {
|
switch (RD->getTagKind()) {
|
||||||
case TTK_Struct: Tag = "struct"; break;
|
case TTK_Struct: Tag = "struct"; break;
|
||||||
case TTK_Interface: Tag = "__interface"; break;
|
case TTK_Interface: Tag = "__interface"; break;
|
||||||
case TTK_Union: Tag = "union"; break;
|
case TTK_Union: Tag = "union"; break;
|
||||||
case TTK_Class: Tag = "class"; break;
|
case TTK_Class: Tag = "class"; break;
|
||||||
case TTK_Enum: Tag = "enum"; break;
|
case TTK_Enum: Tag = "enum"; break;
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl()) {
|
if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl()) {
|
||||||
StringRef Name = TD->getName();
|
StringRef Name = TD->getName();
|
||||||
@ -1220,7 +1224,8 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
|||||||
bool &ok) {
|
bool &ok) {
|
||||||
ok = true;
|
ok = true;
|
||||||
auto PCH = std::make_shared<PCHContainerOperations>();
|
auto PCH = std::make_shared<PCHContainerOperations>();
|
||||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS = llvm::vfs::getRealFileSystem();
|
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS =
|
||||||
|
llvm::vfs::getRealFileSystem();
|
||||||
std::shared_ptr<CompilerInvocation> CI =
|
std::shared_ptr<CompilerInvocation> CI =
|
||||||
BuildCompilerInvocation(main, args, FS);
|
BuildCompilerInvocation(main, args, FS);
|
||||||
// e.g. .s
|
// e.g. .s
|
||||||
@ -1288,12 +1293,14 @@ Index(SemaManager *manager, WorkingFiles *wfiles, VFS *vfs,
|
|||||||
ok = true;
|
ok = true;
|
||||||
};
|
};
|
||||||
if (!CRC.RunSafely(parse)) {
|
if (!CRC.RunSafely(parse)) {
|
||||||
LOG_S(ERROR) << "clang crashed for " << main;
|
if (auto v = Verbosity::ERROR; LogRequire(v))
|
||||||
|
Log(v, "clang crashed for ", main);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
LOG_S(ERROR) << "failed to index " << main;
|
if (auto v = Verbosity::ERROR; LogRequire(v))
|
||||||
|
Log(v, "failed to index ", main);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
for (auto &Buf : Bufs)
|
for (auto &Buf : Bufs)
|
||||||
|
14
src/log.cc
14
src/log.cc
@ -56,11 +56,13 @@ Message::Message(Verbosity verbosity, const char *file, int line)
|
|||||||
stream_ << ' ';
|
stream_ << ' ';
|
||||||
// clang-format off
|
// clang-format off
|
||||||
switch (verbosity_) {
|
switch (verbosity_) {
|
||||||
case Verbosity_FATAL: stream_ << 'F'; break;
|
case Verbosity::FATAL: stream_ << 'F'; break;
|
||||||
case Verbosity_ERROR: stream_ << 'E'; break;
|
case Verbosity::ERROR: stream_ << 'E'; break;
|
||||||
case Verbosity_WARNING: stream_ << 'W'; break;
|
case Verbosity::WARNING: stream_ << 'W'; break;
|
||||||
case Verbosity_INFO: stream_ << 'I'; break;
|
case Verbosity::INFO: stream_ << 'I'; break;
|
||||||
default: stream_ << "V(" << int(verbosity_) << ')';
|
case Verbosity::DEBUG: stream_ << 'D'; break;
|
||||||
|
case Verbosity::VERBOSE: stream_ << 'V'; break;
|
||||||
|
default: stream_ << "V(" << +verbosity_ << ')';
|
||||||
}
|
}
|
||||||
// clang-format on
|
// clang-format on
|
||||||
stream_ << ' ';
|
stream_ << ' ';
|
||||||
@ -73,7 +75,7 @@ Message::~Message() {
|
|||||||
stream_ << '\n';
|
stream_ << '\n';
|
||||||
fputs(stream_.str().c_str(), file);
|
fputs(stream_.str().c_str(), file);
|
||||||
fflush(file);
|
fflush(file);
|
||||||
if (verbosity_ == Verbosity_FATAL)
|
if (verbosity_ == Verbosity::FATAL)
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
} // namespace ccls::log
|
} // namespace ccls::log
|
||||||
|
52
src/log.hh
52
src/log.hh
@ -1,41 +1,45 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
namespace ccls::log {
|
namespace ccls::log {
|
||||||
extern FILE* file;
|
extern FILE *file;
|
||||||
|
|
||||||
struct Voidify {
|
enum class Verbosity : signed {
|
||||||
void operator&(const std::ostream&) {}
|
FATAL = -3,
|
||||||
|
ERROR = -2,
|
||||||
|
WARNING = -1,
|
||||||
|
INFO = 0,
|
||||||
|
DEBUG = 1,
|
||||||
|
VERBOSE = 2
|
||||||
};
|
};
|
||||||
|
template <typename T, typename UT = std::underlying_type_t<T>>
|
||||||
|
constexpr auto operator+(T e) noexcept
|
||||||
|
-> std::enable_if_t<std::is_enum_v<T>, UT> {
|
||||||
|
return static_cast<UT>(e);
|
||||||
|
}
|
||||||
|
|
||||||
enum Verbosity {
|
|
||||||
Verbosity_FATAL = -3,
|
|
||||||
Verbosity_ERROR = -2,
|
|
||||||
Verbosity_WARNING = -1,
|
|
||||||
Verbosity_INFO = 0,
|
|
||||||
};
|
|
||||||
extern Verbosity verbosity;
|
extern Verbosity verbosity;
|
||||||
|
|
||||||
struct Message {
|
struct Message {
|
||||||
std::stringstream stream_;
|
std::stringstream stream_;
|
||||||
int verbosity_;
|
Verbosity verbosity_;
|
||||||
|
|
||||||
Message(Verbosity verbosity, const char* file, int line);
|
Message(Verbosity verbosity, const char *file, int line);
|
||||||
~Message();
|
~Message();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename... Args> inline void Log(Verbosity v, Args const &... args) {
|
||||||
|
(Message(v, __FILE__, __LINE__).stream_ << ... << args);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOG_IF(v, cond) \
|
// XXX: According to CWG 1766, static_cast invalid(out of range) value to enum
|
||||||
!(cond) ? void(0) \
|
// class is UB
|
||||||
: ccls::log::Voidify() & \
|
bool inline LogRequire(Verbosity v) { return +v <= +verbosity; }
|
||||||
ccls::log::Message(v, __FILE__, __LINE__).stream_
|
|
||||||
#define LOG_S(v) \
|
// ADL
|
||||||
LOG_IF(ccls::log::Verbosity_##v, \
|
bool inline LogIf(Verbosity v, bool cond) { return cond && LogRequire(v); }
|
||||||
ccls::log::Verbosity_##v <= ccls::log::verbosity)
|
} // namespace ccls::log
|
||||||
#define LOG_IF_S(v, cond) \
|
|
||||||
LOG_IF(ccls::log::Verbosity_##v, \
|
|
||||||
(cond) && ccls::log::Verbosity_##v <= ccls::log::verbosity)
|
|
||||||
#define LOG_V_ENABLED(v) (v <= ccls::log::verbosity)
|
|
||||||
#define LOG_V(v) LOG_IF(ccls::log::Verbosity(v), LOG_V_ENABLED(v))
|
|
||||||
|
@ -21,6 +21,7 @@ limitations under the License.
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
void Reflect(JsonReader &vis, RequestId &v) {
|
void Reflect(JsonReader &vis, RequestId &v) {
|
||||||
@ -103,9 +104,9 @@ void DocumentUri::SetPath(const std::string &path) {
|
|||||||
|
|
||||||
std::string DocumentUri::GetPath() const {
|
std::string DocumentUri::GetPath() const {
|
||||||
if (raw_uri.compare(0, 7, "file://")) {
|
if (raw_uri.compare(0, 7, "file://")) {
|
||||||
LOG_S(WARNING)
|
if (auto v = Verbosity::WARNING; LogRequire(v))
|
||||||
<< "Received potentially bad URI (not starting with file://): "
|
Log(v, "Received potentially bad URI (not starting with file://): ",
|
||||||
<< raw_uri;
|
raw_uri);
|
||||||
return raw_uri;
|
return raw_uri;
|
||||||
}
|
}
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
@ -13,7 +13,6 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
==============================================================================*/
|
==============================================================================*/
|
||||||
|
|
||||||
#include "sema_manager.hh"
|
|
||||||
#include "filesystem.hh"
|
#include "filesystem.hh"
|
||||||
#include "include_complete.hh"
|
#include "include_complete.hh"
|
||||||
#include "log.hh"
|
#include "log.hh"
|
||||||
@ -21,6 +20,7 @@ limitations under the License.
|
|||||||
#include "pipeline.hh"
|
#include "pipeline.hh"
|
||||||
#include "platform.hh"
|
#include "platform.hh"
|
||||||
#include "project.hh"
|
#include "project.hh"
|
||||||
|
#include "sema_manager.hh"
|
||||||
#include "working_files.hh"
|
#include "working_files.hh"
|
||||||
|
|
||||||
#include <llvm/ADT/Twine.h>
|
#include <llvm/ADT/Twine.h>
|
||||||
@ -29,12 +29,13 @@ limitations under the License.
|
|||||||
#include <rapidjson/document.h>
|
#include <rapidjson/document.h>
|
||||||
#include <rapidjson/writer.h>
|
#include <rapidjson/writer.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
extern std::vector<std::string> g_init_options;
|
extern std::vector<std::string> g_init_options;
|
||||||
|
|
||||||
@ -184,7 +185,8 @@ REFLECT_STRUCT(TextDocumentClientCap::DocumentSymbol,
|
|||||||
hierarchicalDocumentSymbolSupport);
|
hierarchicalDocumentSymbolSupport);
|
||||||
REFLECT_STRUCT(TextDocumentClientCap::LinkSupport, linkSupport);
|
REFLECT_STRUCT(TextDocumentClientCap::LinkSupport, linkSupport);
|
||||||
REFLECT_STRUCT(TextDocumentClientCap::PublishDiagnostics, relatedInformation);
|
REFLECT_STRUCT(TextDocumentClientCap::PublishDiagnostics, relatedInformation);
|
||||||
REFLECT_STRUCT(TextDocumentClientCap, completion, definition, documentSymbol, publishDiagnostics);
|
REFLECT_STRUCT(TextDocumentClientCap, completion, definition, documentSymbol,
|
||||||
|
publishDiagnostics);
|
||||||
|
|
||||||
struct ClientCap {
|
struct ClientCap {
|
||||||
WorkspaceClientCap workspace;
|
WorkspaceClientCap workspace;
|
||||||
@ -268,8 +270,9 @@ void *Indexer(void *arg_) {
|
|||||||
|
|
||||||
void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
||||||
std::string project_path = NormalizePath(param.rootUri->GetPath());
|
std::string project_path = NormalizePath(param.rootUri->GetPath());
|
||||||
LOG_S(INFO) << "initialize in directory " << project_path << " with uri "
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
<< param.rootUri->raw_uri;
|
Log(v, "initialize in directory ", project_path, " with uri ",
|
||||||
|
param.rootUri->raw_uri);
|
||||||
|
|
||||||
{
|
{
|
||||||
g_config = new Config(param.initializationOptions);
|
g_config = new Config(param.initializationOptions);
|
||||||
@ -291,7 +294,8 @@ void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
|||||||
rapidjson::Writer<rapidjson::StringBuffer> writer(output);
|
rapidjson::Writer<rapidjson::StringBuffer> writer(output);
|
||||||
JsonWriter json_writer(&writer);
|
JsonWriter json_writer(&writer);
|
||||||
Reflect(json_writer, *g_config);
|
Reflect(json_writer, *g_config);
|
||||||
LOG_S(INFO) << "initializationOptions: " << output.GetString();
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "initializationOptions: ", output.GetString());
|
||||||
|
|
||||||
if (g_config->cache.directory.size()) {
|
if (g_config->cache.directory.size()) {
|
||||||
SmallString<256> Path(g_config->cache.directory);
|
SmallString<256> Path(g_config->cache.directory);
|
||||||
@ -320,7 +324,8 @@ void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
|||||||
if (g_config->clang.resourceDir.empty())
|
if (g_config->clang.resourceDir.empty())
|
||||||
g_config->clang.resourceDir = GetDefaultResourceDirectory();
|
g_config->clang.resourceDir = GetDefaultResourceDirectory();
|
||||||
DoPathMapping(g_config->clang.resourceDir);
|
DoPathMapping(g_config->clang.resourceDir);
|
||||||
LOG_S(INFO) << "use -resource-dir=" << g_config->clang.resourceDir;
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "use -resource-dir=", g_config->clang.resourceDir);
|
||||||
|
|
||||||
// Send initialization before starting indexers, so we don't send a
|
// Send initialization before starting indexers, so we don't send a
|
||||||
// status update too early.
|
// status update too early.
|
||||||
@ -352,11 +357,12 @@ void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
|||||||
std::sort(workspaceFolders.begin(), workspaceFolders.end(),
|
std::sort(workspaceFolders.begin(), workspaceFolders.end(),
|
||||||
[](auto &l, auto &r) { return l.first.size() > r.first.size(); });
|
[](auto &l, auto &r) { return l.first.size() > r.first.size(); });
|
||||||
for (auto &[folder, real] : workspaceFolders)
|
for (auto &[folder, real] : workspaceFolders)
|
||||||
|
if (auto v = Verbosity::INFO; LogRequire(v)) {
|
||||||
if (real.empty())
|
if (real.empty())
|
||||||
LOG_S(INFO) << "workspace folder: " << folder;
|
Log(v, "workspace folder: ", folder);
|
||||||
else
|
else
|
||||||
LOG_S(INFO) << "workspace folder: " << folder << " -> " << real;
|
Log(v, "workspace folder: ", folder, " -> ", real);
|
||||||
|
}
|
||||||
if (g_config->cache.directory.empty())
|
if (g_config->cache.directory.empty())
|
||||||
g_config->cache.retainInMemory = 1;
|
g_config->cache.retainInMemory = 1;
|
||||||
else if (!g_config->cache.hierarchicalPath)
|
else if (!g_config->cache.hierarchicalPath)
|
||||||
@ -378,7 +384,8 @@ void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
|||||||
if (g_config->index.threads == 0)
|
if (g_config->index.threads == 0)
|
||||||
g_config->index.threads = std::thread::hardware_concurrency();
|
g_config->index.threads = std::thread::hardware_concurrency();
|
||||||
|
|
||||||
LOG_S(INFO) << "start " << g_config->index.threads << " indexers";
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "start ", g_config->index.threads, " indexers");
|
||||||
for (int i = 0; i < g_config->index.threads; i++)
|
for (int i = 0; i < g_config->index.threads; i++)
|
||||||
SpawnThread(Indexer, new std::pair<MessageHandler *, int>{m, i});
|
SpawnThread(Indexer, new std::pair<MessageHandler *, int>{m, i});
|
||||||
|
|
||||||
@ -386,7 +393,8 @@ void Initialize(MessageHandler *m, InitializeParam ¶m, ReplyOnce &reply) {
|
|||||||
// files, because that takes a long time.
|
// files, because that takes a long time.
|
||||||
m->include_complete->Rescan();
|
m->include_complete->Rescan();
|
||||||
|
|
||||||
LOG_S(INFO) << "dispatch initial index requests";
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "dispatch initial index requests");
|
||||||
m->project->Index(m->wfiles, reply.id);
|
m->project->Index(m->wfiles, reply.id);
|
||||||
|
|
||||||
m->manager->sessions.SetCapacity(g_config->session.maxNum);
|
m->manager->sessions.SetCapacity(g_config->session.maxNum);
|
||||||
|
@ -31,6 +31,7 @@ limitations under the License.
|
|||||||
namespace ccls {
|
namespace ccls {
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
REFLECT_UNDERLYING(InsertTextFormat);
|
REFLECT_UNDERLYING(InsertTextFormat);
|
||||||
REFLECT_UNDERLYING(CompletionItemKind);
|
REFLECT_UNDERLYING(CompletionItemKind);
|
||||||
@ -61,8 +62,7 @@ REFLECT_STRUCT(CompletionList, isIncomplete, items);
|
|||||||
|
|
||||||
#if LLVM_VERSION_MAJOR < 8
|
#if LLVM_VERSION_MAJOR < 8
|
||||||
void DecorateIncludePaths(const std::smatch &match,
|
void DecorateIncludePaths(const std::smatch &match,
|
||||||
std::vector<CompletionItem> *items,
|
std::vector<CompletionItem> *items, char quote) {
|
||||||
char quote) {
|
|
||||||
std::string spaces_after_include = " ";
|
std::string spaces_after_include = " ";
|
||||||
if (match[3].compare("include") == 0 && quote != '\0')
|
if (match[3].compare("include") == 0 && quote != '\0')
|
||||||
spaces_after_include = match[4].str();
|
spaces_after_include = match[4].str();
|
||||||
@ -161,12 +161,15 @@ void FilterCandidates(CompletionList &result, const std::string &complete_text,
|
|||||||
auto &edits = item.additionalTextEdits;
|
auto &edits = item.additionalTextEdits;
|
||||||
if (overwrite_len > 0) {
|
if (overwrite_len > 0) {
|
||||||
item.textEdit.range.start = overwrite_begin;
|
item.textEdit.range.start = overwrite_begin;
|
||||||
std::string orig = buffer_line.substr(overwrite_begin.character, overwrite_len);
|
std::string orig =
|
||||||
|
buffer_line.substr(overwrite_begin.character, overwrite_len);
|
||||||
if (edits.size() && edits[0].range.end == begin_pos &&
|
if (edits.size() && edits[0].range.end == begin_pos &&
|
||||||
edits[0].range.start.line == begin_pos.line) {
|
edits[0].range.start.line == begin_pos.line) {
|
||||||
int cur_edit_len = edits[0].range.end.character - edits[0].range.start.character;
|
int cur_edit_len =
|
||||||
|
edits[0].range.end.character - edits[0].range.start.character;
|
||||||
item.textEdit.newText =
|
item.textEdit.newText =
|
||||||
buffer_line.substr(overwrite_begin.character, overwrite_len - cur_edit_len) +
|
buffer_line.substr(overwrite_begin.character,
|
||||||
|
overwrite_len - cur_edit_len) +
|
||||||
edits[0].newText + item.textEdit.newText;
|
edits[0].newText + item.textEdit.newText;
|
||||||
edits.erase(edits.begin());
|
edits.erase(edits.begin());
|
||||||
} else {
|
} else {
|
||||||
@ -304,7 +307,8 @@ CompletionItemKind GetCompletionKind(CodeCompletionContext::Kind K,
|
|||||||
return CompletionItemKind::Field;
|
return CompletionItemKind::Field;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_S(WARNING) << "Unhandled " << int(D->getKind());
|
if (auto v = Verbosity::WARNING; LogRequire(v))
|
||||||
|
Log(v, "Unhandled ", int(D->getKind()));
|
||||||
return CompletionItemKind::Text;
|
return CompletionItemKind::Text;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -13,13 +13,13 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
==============================================================================*/
|
==============================================================================*/
|
||||||
|
|
||||||
#include "sema_manager.hh"
|
|
||||||
#include "fuzzy_match.hh"
|
#include "fuzzy_match.hh"
|
||||||
#include "log.hh"
|
#include "log.hh"
|
||||||
#include "message_handler.hh"
|
#include "message_handler.hh"
|
||||||
#include "pipeline.hh"
|
#include "pipeline.hh"
|
||||||
#include "project.hh"
|
#include "project.hh"
|
||||||
#include "query.hh"
|
#include "query.hh"
|
||||||
|
#include "sema_manager.hh"
|
||||||
|
|
||||||
#include <llvm/ADT/STLExtras.h>
|
#include <llvm/ADT/STLExtras.h>
|
||||||
#include <llvm/ADT/StringRef.h>
|
#include <llvm/ADT/StringRef.h>
|
||||||
@ -30,6 +30,7 @@ limitations under the License.
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName);
|
REFLECT_STRUCT(SymbolInformation, name, kind, location, containerName);
|
||||||
@ -81,7 +82,8 @@ void MessageHandler::workspace_didChangeWorkspaceFolders(
|
|||||||
for (const WorkspaceFolder &wf : param.event.removed) {
|
for (const WorkspaceFolder &wf : param.event.removed) {
|
||||||
std::string root = wf.uri.GetPath();
|
std::string root = wf.uri.GetPath();
|
||||||
EnsureEndsInSlash(root);
|
EnsureEndsInSlash(root);
|
||||||
LOG_S(INFO) << "delete workspace folder " << wf.name << ": " << root;
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "delete workspace folder ", wf.name, ": ", root);
|
||||||
auto it = llvm::find_if(g_config->workspaceFolders,
|
auto it = llvm::find_if(g_config->workspaceFolders,
|
||||||
[&](auto &folder) { return folder.first == root; });
|
[&](auto &folder) { return folder.first == root; });
|
||||||
if (it != g_config->workspaceFolders.end()) {
|
if (it != g_config->workspaceFolders.end()) {
|
||||||
@ -100,8 +102,9 @@ void MessageHandler::workspace_didChangeWorkspaceFolders(
|
|||||||
std::string real = RealPath(folder) + '/';
|
std::string real = RealPath(folder) + '/';
|
||||||
if (folder == real)
|
if (folder == real)
|
||||||
real.clear();
|
real.clear();
|
||||||
LOG_S(INFO) << "add workspace folder " << wf.name << ": "
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
<< (real.empty() ? folder : folder + " -> " + real);
|
Log(v, "add workspace folder ", wf.name, ": ",
|
||||||
|
(real.empty() ? folder : folder + " -> " + real));
|
||||||
workspaceFolders.emplace_back();
|
workspaceFolders.emplace_back();
|
||||||
auto it = workspaceFolders.end() - 1;
|
auto it = workspaceFolders.end() - 1;
|
||||||
for (; it != workspaceFolders.begin() && folder < it[-1].first; --it)
|
for (; it != workspaceFolders.begin() && folder < it[-1].first; --it)
|
||||||
|
@ -41,6 +41,7 @@ limitations under the License.
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
namespace chrono = std::chrono;
|
namespace chrono = std::chrono;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
@ -118,8 +119,9 @@ bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path,
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(vfs->mutex);
|
std::lock_guard<std::mutex> lock(vfs->mutex);
|
||||||
if (prev->mtime < vfs->state[path].timestamp) {
|
if (prev->mtime < vfs->state[path].timestamp) {
|
||||||
LOG_V(1) << "timestamp changed for " << path
|
if (auto v = Verbosity::DEBUG; LogRequire(v))
|
||||||
<< (from ? " (via " + *from + ")" : std::string());
|
Log(v, "timestamp changed for ", path,
|
||||||
|
(from ? " (via " + *from + ")" : std::string()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,8 +133,9 @@ bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path,
|
|||||||
if (strcmp(prev->args[i], args[i]) && sys::path::stem(args[i]) != stem)
|
if (strcmp(prev->args[i], args[i]) && sys::path::stem(args[i]) != stem)
|
||||||
changed = true;
|
changed = true;
|
||||||
if (changed)
|
if (changed)
|
||||||
LOG_V(1) << "args changed for " << path
|
if (auto v = Verbosity::DEBUG; LogRequire(v))
|
||||||
<< (from ? " (via " + *from + ")" : std::string());
|
Log(v, "args changed for ", path,
|
||||||
|
(from ? " (via " + *from + ")" : std::string()));
|
||||||
return changed;
|
return changed;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -215,7 +218,8 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!matcher.Matches(request.path)) {
|
if (!matcher.Matches(request.path)) {
|
||||||
LOG_IF_S(INFO, loud) << "skip " << request.path;
|
if (auto v = Verbosity::INFO; LogIf(v, loud))
|
||||||
|
Log(v, "skip ", request.path);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -271,14 +275,16 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
|
|||||||
if (auto mtime1 = LastWriteTime(dep.first.val().str())) {
|
if (auto mtime1 = LastWriteTime(dep.first.val().str())) {
|
||||||
if (dep.second < *mtime1) {
|
if (dep.second < *mtime1) {
|
||||||
reparse = 2;
|
reparse = 2;
|
||||||
LOG_V(1) << "timestamp changed for " << path_to_index << " via "
|
if (auto v = Verbosity::DEBUG; LogRequire(v))
|
||||||
<< dep.first.val().str();
|
Log(v, "timestamp changed for ", path_to_index, " via ",
|
||||||
|
dep.first.val().str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reparse = 2;
|
reparse = 2;
|
||||||
LOG_V(1) << "timestamp changed for " << path_to_index << " via "
|
if (auto v = Verbosity::DEBUG; LogRequire(v))
|
||||||
<< dep.first.val().str();
|
Log(v, "timestamp changed for ", path_to_index, " via ",
|
||||||
|
dep.first.val().str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -289,7 +295,8 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
|
|||||||
|
|
||||||
if (vfs->Loaded(path_to_index))
|
if (vfs->Loaded(path_to_index))
|
||||||
return true;
|
return true;
|
||||||
LOG_S(INFO) << "load cache for " << path_to_index;
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "load cache for ", path_to_index);
|
||||||
auto dependencies = prev->dependencies;
|
auto dependencies = prev->dependencies;
|
||||||
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
|
IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get());
|
||||||
on_indexed->PushBack(std::move(update),
|
on_indexed->PushBack(std::move(update),
|
||||||
@ -329,12 +336,13 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
|
|||||||
|
|
||||||
if (loud) {
|
if (loud) {
|
||||||
std::string line;
|
std::string line;
|
||||||
if (LOG_V_ENABLED(1)) {
|
if (LogRequire(Verbosity::DEBUG)) {
|
||||||
line = "\n ";
|
line = "\n ";
|
||||||
for (auto &arg : entry.args)
|
for (auto &arg : entry.args)
|
||||||
(line += ' ') += arg;
|
(line += ' ') += arg;
|
||||||
}
|
}
|
||||||
LOG_S(INFO) << (deleted ? "delete " : "parse ") << path_to_index << line;
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, (deleted ? "delete " : "parse "), path_to_index, line);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::unique_ptr<IndexFile>> indexes;
|
std::vector<std::unique_ptr<IndexFile>> indexes;
|
||||||
@ -367,13 +375,13 @@ bool Indexer_Parse(SemaManager *completion, WorkingFiles *wfiles,
|
|||||||
for (std::unique_ptr<IndexFile> &curr : indexes) {
|
for (std::unique_ptr<IndexFile> &curr : indexes) {
|
||||||
std::string path = curr->path;
|
std::string path = curr->path;
|
||||||
if (!matcher.Matches(path)) {
|
if (!matcher.Matches(path)) {
|
||||||
LOG_IF_S(INFO, loud) << "skip index for " << path;
|
if (auto v = Verbosity::INFO; LogIf(Verbosity::INFO, loud))
|
||||||
|
Log(v, "skip index for ", path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deleted)
|
if (auto v = Verbosity::INFO; LogIf(v, loud) && !deleted)
|
||||||
LOG_IF_S(INFO, loud) << "store index for " << path
|
Log(v, "store index for ", path, " (delta: ", !!prev, ")");
|
||||||
<< " (delta: " << !!prev << ")";
|
|
||||||
{
|
{
|
||||||
std::lock_guard lock(GetFileMutex(path));
|
std::lock_guard lock(GetFileMutex(path));
|
||||||
int loaded = vfs->Loaded(path), retain = g_config->cache.retainInMemory;
|
int loaded = vfs->Loaded(path), retain = g_config->cache.retainInMemory;
|
||||||
@ -468,8 +476,9 @@ void Indexer_Main(SemaManager *manager, VFS *vfs, Project *project,
|
|||||||
|
|
||||||
void Main_OnIndexed(DB *db, WorkingFiles *wfiles, IndexUpdate *update) {
|
void Main_OnIndexed(DB *db, WorkingFiles *wfiles, IndexUpdate *update) {
|
||||||
if (update->refresh) {
|
if (update->refresh) {
|
||||||
LOG_S(INFO)
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
<< "loaded project. Refresh semantic highlight for all working file.";
|
Log(v,
|
||||||
|
"loaded project. Refresh semantic highlight for all working file.");
|
||||||
std::lock_guard lock(wfiles->mutex);
|
std::lock_guard lock(wfiles->mutex);
|
||||||
for (auto &[f, wf] : wfiles->files) {
|
for (auto &[f, wf] : wfiles->files) {
|
||||||
std::string path = LowerPathIfInsensitive(f);
|
std::string path = LowerPathIfInsensitive(f);
|
||||||
@ -545,10 +554,12 @@ void LaunchStdin() {
|
|||||||
std::string method;
|
std::string method;
|
||||||
ReflectMember(reader, "id", id);
|
ReflectMember(reader, "id", id);
|
||||||
ReflectMember(reader, "method", method);
|
ReflectMember(reader, "method", method);
|
||||||
|
if (auto v = Verbosity::VERBOSE; LogRequire(v)) {
|
||||||
if (id.Valid())
|
if (id.Valid())
|
||||||
LOG_V(2) << "receive RequestMessage: " << id.value << " " << method;
|
Log(v, "receive RequestMessage: ", id.value, " ", method);
|
||||||
else
|
else
|
||||||
LOG_V(2) << "receive NotificationMessage " << method;
|
Log(v, "receive NotificationMessage ", method);
|
||||||
|
}
|
||||||
if (method.empty())
|
if (method.empty())
|
||||||
continue;
|
continue;
|
||||||
received_exit = method == "exit";
|
received_exit = method == "exit";
|
||||||
@ -574,7 +585,8 @@ void LaunchStdin() {
|
|||||||
chrono::steady_clock::now()});
|
chrono::steady_clock::now()});
|
||||||
}
|
}
|
||||||
ThreadLeave();
|
ThreadLeave();
|
||||||
}).detach();
|
})
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LaunchStdout() {
|
void LaunchStdout() {
|
||||||
@ -592,7 +604,8 @@ void LaunchStdout() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ThreadLeave();
|
ThreadLeave();
|
||||||
}).detach();
|
})
|
||||||
|
.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainLoop() {
|
void MainLoop() {
|
||||||
@ -702,8 +715,8 @@ void Standalone(const std::string &root) {
|
|||||||
Project project;
|
Project project;
|
||||||
WorkingFiles wfiles;
|
WorkingFiles wfiles;
|
||||||
VFS vfs;
|
VFS vfs;
|
||||||
SemaManager manager(
|
SemaManager manager(nullptr, nullptr,
|
||||||
nullptr, nullptr, [&](std::string, std::vector<Diagnostic>) {},
|
[&](std::string, std::vector<Diagnostic>) {},
|
||||||
[](RequestId id) {});
|
[](RequestId id) {});
|
||||||
IncludeComplete complete(&project);
|
IncludeComplete complete(&project);
|
||||||
|
|
||||||
@ -781,7 +794,8 @@ void NotifyOrRequest(const char *method, bool request,
|
|||||||
JsonWriter writer(&w);
|
JsonWriter writer(&w);
|
||||||
fn(writer);
|
fn(writer);
|
||||||
w.EndObject();
|
w.EndObject();
|
||||||
LOG_V(2) << (request ? "RequestMessage: " : "NotificationMessage: ") << method;
|
if (auto v = Verbosity::VERBOSE; LogRequire(v))
|
||||||
|
Log(v, (request ? "RequestMessage: " : "NotificationMessage: "), method);
|
||||||
for_stdout->PushBack(output.GetString());
|
for_stdout->PushBack(output.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,8 +823,8 @@ static void Reply(RequestId id, const char *key,
|
|||||||
JsonWriter writer(&w);
|
JsonWriter writer(&w);
|
||||||
fn(writer);
|
fn(writer);
|
||||||
w.EndObject();
|
w.EndObject();
|
||||||
if (id.Valid())
|
if (auto v = Verbosity::VERBOSE; LogRequire(v) && id.Valid())
|
||||||
LOG_V(2) << "respond to RequestMessage: " << id.value;
|
Log(v, "respond to RequestMessage: ", id.value);
|
||||||
for_stdout->PushBack(output.GetString());
|
for_stdout->PushBack(output.GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,9 +37,9 @@ limitations under the License.
|
|||||||
#include <rapidjson/writer.h>
|
#include <rapidjson/writer.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <Windows.h>
|
#include <Windows.h>
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
@ -49,6 +49,7 @@ limitations under the License.
|
|||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
std::pair<LanguageId, bool> lookupExtension(std::string_view filename) {
|
std::pair<LanguageId, bool> lookupExtension(std::string_view filename) {
|
||||||
@ -91,13 +92,17 @@ struct ProjectProcessor {
|
|||||||
exclude_args.insert(arg);
|
exclude_args.insert(arg);
|
||||||
else if (Expected<GlobPattern> glob_or_err = GlobPattern::create(arg))
|
else if (Expected<GlobPattern> glob_or_err = GlobPattern::create(arg))
|
||||||
exclude_globs.push_back(std::move(*glob_or_err));
|
exclude_globs.push_back(std::move(*glob_or_err));
|
||||||
else
|
else {
|
||||||
LOG_S(WARNING) << toString(glob_or_err.takeError());
|
if (auto v = Verbosity::WARNING; LogRequire(v))
|
||||||
|
Log(v, toString(glob_or_err.takeError()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExcludesArg(StringRef arg) {
|
bool ExcludesArg(StringRef arg) {
|
||||||
|
// clang-format off
|
||||||
return exclude_args.count(arg) || any_of(exclude_globs,
|
return exclude_args.count(arg) || any_of(exclude_globs,
|
||||||
[&](const GlobPattern &glob) { return glob.match(arg); });
|
[&](const GlobPattern &glob) { return glob.match(arg); });
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand %c %cpp ... in .ccls
|
// Expand %c %cpp ... in .ccls
|
||||||
@ -265,7 +270,8 @@ void LoadDirectoryListing(ProjectProcessor &proc, const std::string &root,
|
|||||||
return folder.dot_ccls[root];
|
return folder.dot_ccls[root];
|
||||||
};
|
};
|
||||||
|
|
||||||
GetFilesInFolder(root, true /*recursive*/, true /*add_folder_to_path*/,
|
GetFilesInFolder(
|
||||||
|
root, true /*recursive*/, true /*add_folder_to_path*/,
|
||||||
[&folder, &files, &Seen](const std::string &path) {
|
[&folder, &files, &Seen](const std::string &path) {
|
||||||
std::pair<LanguageId, bool> lang = lookupExtension(path);
|
std::pair<LanguageId, bool> lang = lookupExtension(path);
|
||||||
if (lang.first != LanguageId::Unknown && !lang.second) {
|
if (lang.first != LanguageId::Unknown && !lang.second) {
|
||||||
@ -273,15 +279,15 @@ void LoadDirectoryListing(ProjectProcessor &proc, const std::string &root,
|
|||||||
files.push_back(path);
|
files.push_back(path);
|
||||||
} else if (sys::path::filename(path) == ".ccls") {
|
} else if (sys::path::filename(path) == ".ccls") {
|
||||||
std::vector<const char *> args = ReadCompilerArgumentsFromFile(path);
|
std::vector<const char *> args = ReadCompilerArgumentsFromFile(path);
|
||||||
folder.dot_ccls.emplace(sys::path::parent_path(path),
|
folder.dot_ccls.emplace(sys::path::parent_path(path), args);
|
||||||
args);
|
|
||||||
std::string l;
|
std::string l;
|
||||||
for (size_t i = 0; i < args.size(); i++) {
|
for (size_t i = 0; i < args.size(); i++) {
|
||||||
if (i)
|
if (i)
|
||||||
l += ' ';
|
l += ' ';
|
||||||
l += args[i];
|
l += args[i];
|
||||||
}
|
}
|
||||||
LOG_S(INFO) << "use " << path << ": " << l;
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "use ", path, ": ", l);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -367,8 +373,9 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
|
|||||||
std::vector<StringRef> args{g_config->compilationDatabaseCommand, root};
|
std::vector<StringRef> args{g_config->compilationDatabaseCommand, root};
|
||||||
if (sys::ExecuteAndWait(args[0], args, llvm::None, Redir, 0, 0, &err_msg) <
|
if (sys::ExecuteAndWait(args[0], args, llvm::None, Redir, 0, 0, &err_msg) <
|
||||||
0) {
|
0) {
|
||||||
LOG_S(ERROR) << "failed to execute " << args[0].str() << " "
|
if (auto v = Verbosity::ERROR; LogRequire(v))
|
||||||
<< args[1].str() << ": " << err_msg;
|
Log(v, "failed to execute ", args[0].str(), " ", args[1].str(), ": ",
|
||||||
|
err_msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -392,9 +399,11 @@ void Project::LoadDirectory(const std::string &root, Project::Folder &folder) {
|
|||||||
std::vector<Project::Entry> result;
|
std::vector<Project::Entry> result;
|
||||||
if (!CDB) {
|
if (!CDB) {
|
||||||
if (g_config->compilationDatabaseCommand.size() || sys::fs::exists(Path))
|
if (g_config->compilationDatabaseCommand.size() || sys::fs::exists(Path))
|
||||||
LOG_S(ERROR) << "failed to load " << Path.c_str();
|
if (auto v = Verbosity::ERROR; LogRequire(v))
|
||||||
|
Log(v, "failed to load ", Path.c_str());
|
||||||
} else {
|
} else {
|
||||||
LOG_S(INFO) << "loaded " << Path.c_str();
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "loaded ", Path.c_str());
|
||||||
for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) {
|
for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) {
|
||||||
static bool once;
|
static bool once;
|
||||||
Project::Entry entry;
|
Project::Entry entry;
|
||||||
@ -458,7 +467,8 @@ void Project::Load(const std::string &root) {
|
|||||||
|
|
||||||
LoadDirectory(root, folder);
|
LoadDirectory(root, folder);
|
||||||
for (auto &[path, kind] : folder.search_dir2kind)
|
for (auto &[path, kind] : folder.search_dir2kind)
|
||||||
LOG_S(INFO) << "search directory: " << path << ' ' << " \"< "[kind];
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "search directory: ", path, ' ', " \"< "[kind]);
|
||||||
|
|
||||||
// Setup project entries.
|
// Setup project entries.
|
||||||
folder.path2entry_index.reserve(folder.entries.size());
|
folder.path2entry_index.reserve(folder.entries.size());
|
||||||
@ -579,8 +589,9 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) {
|
|||||||
: IndexMode::NonInteractive,
|
: IndexMode::NonInteractive,
|
||||||
false, id);
|
false, id);
|
||||||
} else {
|
} else {
|
||||||
LOG_V(1) << "[" << i << "/" << folder.entries.size() << "]: " << reason
|
if (auto v = Verbosity::DEBUG; LogRequire(v))
|
||||||
<< "; skip " << entry.filename;
|
Log(v, "[", i, "/", folder.entries.size(), "]: ", reason, "; skip ",
|
||||||
|
entry.filename);
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ limitations under the License.
|
|||||||
#include <llvm/Support/Threading.h>
|
#include <llvm/Support/Threading.h>
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@ -722,12 +723,13 @@ SemaManager::EnsureSession(const std::string &path, bool *created) {
|
|||||||
session = std::make_shared<ccls::Session>(
|
session = std::make_shared<ccls::Session>(
|
||||||
project_->FindEntry(path, false, false), wfiles, PCH);
|
project_->FindEntry(path, false, false), wfiles, PCH);
|
||||||
std::string line;
|
std::string line;
|
||||||
if (LOG_V_ENABLED(1)) {
|
if (LogRequire(Verbosity::DEBUG)) {
|
||||||
line = "\n ";
|
line = "\n ";
|
||||||
for (auto &arg : session->file.args)
|
for (auto &arg : session->file.args)
|
||||||
(line += ' ') += arg;
|
(line += ' ') += arg;
|
||||||
}
|
}
|
||||||
LOG_S(INFO) << "create session for " << path << line;
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "create session for ", path, line);
|
||||||
sessions.Insert(path, session);
|
sessions.Insert(path, session);
|
||||||
if (created)
|
if (created)
|
||||||
*created = true;
|
*created = true;
|
||||||
@ -736,7 +738,8 @@ SemaManager::EnsureSession(const std::string &path, bool *created) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SemaManager::Clear() {
|
void SemaManager::Clear() {
|
||||||
LOG_S(INFO) << "clear all sessions";
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "clear all sessions");
|
||||||
std::lock_guard lock(mutex);
|
std::lock_guard lock(mutex);
|
||||||
sessions.Clear();
|
sessions.Clear();
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ limitations under the License.
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
bool gTestOutputMode = false;
|
bool gTestOutputMode = false;
|
||||||
|
|
||||||
@ -426,9 +427,7 @@ CachedHashStringRef InternH(StringRef S) {
|
|||||||
return *R.first;
|
return *R.first;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *Intern(StringRef S) {
|
const char *Intern(StringRef S) { return InternH(S).val().data(); }
|
||||||
return InternH(S).val().data();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Serialize(SerializeFormat format, IndexFile &file) {
|
std::string Serialize(SerializeFormat format, IndexFile &file) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
@ -485,7 +484,8 @@ Deserialize(SerializeFormat format, const std::string &path,
|
|||||||
file = std::make_unique<IndexFile>(path, file_content);
|
file = std::make_unique<IndexFile>(path, file_content);
|
||||||
ReflectFile(reader, *file);
|
ReflectFile(reader, *file);
|
||||||
} catch (std::invalid_argument &e) {
|
} catch (std::invalid_argument &e) {
|
||||||
LOG_S(INFO) << "failed to deserialize '" << path << "': " << e.what();
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
|
Log(v, "failed to deserialize '", path, "': ", e.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -510,8 +510,9 @@ Deserialize(SerializeFormat format, const std::string &path,
|
|||||||
try {
|
try {
|
||||||
ReflectFile(json_reader, *file);
|
ReflectFile(json_reader, *file);
|
||||||
} catch (std::invalid_argument &e) {
|
} catch (std::invalid_argument &e) {
|
||||||
LOG_S(INFO) << "'" << path << "': failed to deserialize "
|
if (auto v = Verbosity::INFO; LogRequire(v))
|
||||||
<< json_reader.GetPath() << "." << e.what();
|
Log(v, "'", path, "': failed to deserialize ", json_reader.GetPath(),
|
||||||
|
".", e.what());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -36,6 +36,7 @@ limitations under the License.
|
|||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
struct Matcher::Impl {
|
struct Matcher::Impl {
|
||||||
@ -182,7 +183,8 @@ void WriteToFile(const std::string &filename, const std::string &content) {
|
|||||||
FILE *f = fopen(filename.c_str(), "wb");
|
FILE *f = fopen(filename.c_str(), "wb");
|
||||||
if (!f ||
|
if (!f ||
|
||||||
(content.size() && fwrite(content.c_str(), content.size(), 1, f) != 1)) {
|
(content.size() && fwrite(content.c_str(), content.size(), 1, f) != 1)) {
|
||||||
LOG_S(ERROR) << "failed to write to " << filename << ' ' << strerror(errno);
|
if (auto v = Verbosity::ERROR; LogRequire(v))
|
||||||
|
Log(v, "failed to write to ", filename, ' ', strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fclose(f);
|
fclose(f);
|
||||||
@ -206,4 +208,4 @@ int ReverseSubseqMatch(std::string_view pat, std::string_view text,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string GetDefaultResourceDirectory() { return DEFAULT_RESOURCE_DIRECTORY; }
|
std::string GetDefaultResourceDirectory() { return DEFAULT_RESOURCE_DIRECTORY; }
|
||||||
}
|
} // namespace ccls
|
||||||
|
@ -28,6 +28,7 @@ namespace chrono = std::chrono;
|
|||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
using namespace ccls::log;
|
||||||
|
|
||||||
namespace ccls {
|
namespace ccls {
|
||||||
namespace {
|
namespace {
|
||||||
@ -329,8 +330,9 @@ std::optional<int> WorkingFile::GetBufferPosFromIndexPos(int line, int *column,
|
|||||||
if (line == (int)index_lines.size() && !*column)
|
if (line == (int)index_lines.size() && !*column)
|
||||||
return buffer_content.size();
|
return buffer_content.size();
|
||||||
if (line < 0 || line >= (int)index_lines.size()) {
|
if (line < 0 || line >= (int)index_lines.size()) {
|
||||||
LOG_S(WARNING) << "bad index_line (got " << line << ", expected [0, "
|
if (auto v = Verbosity::WARNING; LogRequire(v))
|
||||||
<< index_lines.size() << ")) in " << filename;
|
Log(v, "bad index_line (got ", line, ", expected [0, ",
|
||||||
|
index_lines.size(), ")) in ", filename);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -406,7 +408,8 @@ void WorkingFiles::OnChange(const TextDocumentDidChangeParam &change) {
|
|||||||
std::string path = change.textDocument.uri.GetPath();
|
std::string path = change.textDocument.uri.GetPath();
|
||||||
WorkingFile *file = GetFileUnlocked(path);
|
WorkingFile *file = GetFileUnlocked(path);
|
||||||
if (!file) {
|
if (!file) {
|
||||||
LOG_S(WARNING) << "Could not change " << path << " because it was not open";
|
if (auto v = Verbosity::WARNING; LogRequire(v))
|
||||||
|
Log(v,"Could not change ", path, " because it was not open");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,4 +485,4 @@ std::string_view LexIdentifierAroundPos(Position position,
|
|||||||
|
|
||||||
return content.substr(start, end - start);
|
return content.substr(start, end - start);
|
||||||
}
|
}
|
||||||
}
|
} // namespace ccls
|
||||||
|
Loading…
Reference in New Issue
Block a user