Refactor Matcher to use pimpl and merge match.hh into utils.hh

This commit is contained in:
Fangrui Song 2018-11-26 22:22:27 -08:00
parent 38e87a0729
commit d6dd932e6d
12 changed files with 90 additions and 116 deletions

View File

@ -190,7 +190,6 @@ target_sources(ccls PRIVATE
src/indexer.cc src/indexer.cc
src/log.cc src/log.cc
src/lsp.cc src/lsp.cc
src/match.cc
src/message_handler.cc src/message_handler.cc
src/pipeline.cc src/pipeline.cc
src/platform_posix.cc src/platform_posix.cc

View File

@ -6,7 +6,6 @@
#include "clang_tu.hh" #include "clang_tu.hh"
#include "filesystem.hh" #include "filesystem.hh"
#include "log.hh" #include "log.hh"
#include "match.hh"
#include "platform.hh" #include "platform.hh"
#include <clang/Lex/PreprocessorOptions.h> #include <clang/Lex/PreprocessorOptions.h>
@ -574,7 +573,7 @@ void CompletionManager::DiagnosticsUpdate(const std::string &path,
int debounce) { int debounce) {
static GroupMatch match(g_config->diagnostics.whitelist, static GroupMatch match(g_config->diagnostics.whitelist,
g_config->diagnostics.blacklist); g_config->diagnostics.blacklist);
if (!match.IsMatch(path)) if (!match.Matches(path))
return; return;
int64_t now = chrono::duration_cast<chrono::milliseconds>( int64_t now = chrono::duration_cast<chrono::milliseconds>(
chrono::high_resolution_clock::now().time_since_epoch()) chrono::high_resolution_clock::now().time_since_epoch())

View File

@ -4,7 +4,6 @@
#include "include_complete.hh" #include "include_complete.hh"
#include "filesystem.hh" #include "filesystem.hh"
#include "match.hh"
#include "platform.hh" #include "platform.hh"
#include "project.hh" #include "project.hh"
@ -150,7 +149,7 @@ void IncludeComplete::AddFile(const std::string &path) {
ok = true; ok = true;
if (!ok) if (!ok)
return; return;
if (match_ && !match_->IsMatch(path)) if (match_ && !match_->Matches(path))
return; return;
std::string trimmed_path = path; std::string trimmed_path = path;
@ -167,7 +166,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory,
bool use_angle_brackets) { bool use_angle_brackets) {
directory = NormalizePath(directory); directory = NormalizePath(directory);
EnsureEndsInSlash(directory); EnsureEndsInSlash(directory);
if (match_ && !match_->IsMatch(directory)) if (match_ && !match_->Matches(directory))
return; return;
bool include_cpp = directory.find("include/c++") != std::string::npos; bool include_cpp = directory.find("include/c++") != std::string::npos;
@ -181,7 +180,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory,
ok = true; ok = true;
if (!ok) if (!ok)
return; return;
if (match_ && !match_->IsMatch(directory + path)) if (match_ && !match_->Matches(directory + path))
return; return;
CompletionCandidate candidate; CompletionCandidate candidate;

View File

@ -6,7 +6,6 @@
#include "clang_complete.hh" #include "clang_complete.hh"
#include "clang_tu.hh" #include "clang_tu.hh"
#include "log.hh" #include "log.hh"
#include "match.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
#include "serializer.hh" #include "serializer.hh"
@ -85,7 +84,7 @@ struct IndexParam {
bool UseMultiVersion(const FileEntry &FE) { bool UseMultiVersion(const FileEntry &FE) {
auto it = UID2multi.try_emplace(FE.getUniqueID()); auto it = UID2multi.try_emplace(FE.getUniqueID());
if (it.second) if (it.second)
it.first->second = multiVersionMatcher->IsMatch(PathFromFileEntry(FE)); it.first->second = multiVersionMatcher->Matches(PathFromFileEntry(FE));
return it.first->second; return it.first->second;
} }
}; };

View File

@ -1,65 +0,0 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0
#include "match.hh"
#include "message_handler.hh"
#include "pipeline.hh"
namespace ccls {
std::optional<Matcher> Matcher::Create(const std::string &search) {
try {
Matcher m;
m.regex_string = search;
m.regex = std::regex(search, std::regex_constants::ECMAScript |
std::regex_constants::icase |
std::regex_constants::optimize
// std::regex_constants::nosubs
);
return m;
} catch (const std::exception &e) {
ShowMessageParam params;
params.type = MessageType::Error;
params.message =
"failed to parse EMCAScript regex " + search + " : " + e.what();
pipeline::Notify(window_showMessage, params);
return std::nullopt;
}
}
bool Matcher::IsMatch(const std::string &value) const {
// std::smatch match;
// return std::regex_match(value, match, regex);
return std::regex_search(value, regex, std::regex_constants::match_any);
}
GroupMatch::GroupMatch(const std::vector<std::string> &whitelist,
const std::vector<std::string> &blacklist) {
for (const std::string &entry : whitelist) {
std::optional<Matcher> m = Matcher::Create(entry);
if (m)
this->whitelist.push_back(*m);
}
for (const std::string &entry : blacklist) {
std::optional<Matcher> m = Matcher::Create(entry);
if (m)
this->blacklist.push_back(*m);
}
}
bool GroupMatch::IsMatch(const std::string &value,
std::string *match_failure_reason) const {
for (const Matcher &m : whitelist)
if (m.IsMatch(value))
return true;
for (const Matcher &m : blacklist)
if (m.IsMatch(value)) {
if (match_failure_reason)
*match_failure_reason = "blacklist \"" + m.regex_string + "\"";
return false;
}
return true;
}
} // namespace ccls

View File

@ -1,33 +0,0 @@
// Copyright 2017-2018 ccls Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <optional>
#include <regex>
#include <string>
#include <vector>
namespace ccls {
struct Matcher {
static std::optional<Matcher> Create(const std::string &search);
bool IsMatch(const std::string &value) const;
std::string regex_string;
std::regex regex;
};
// Check multiple |Matcher| instances at the same time.
struct GroupMatch {
GroupMatch(const std::vector<std::string> &whitelist,
const std::vector<std::string> &blacklist);
bool IsMatch(const std::string &value,
std::string *match_failure_reason = nullptr) const;
std::vector<Matcher> whitelist;
std::vector<Matcher> blacklist;
};
} // namespace ccls

View File

@ -4,7 +4,6 @@
#include "message_handler.hh" #include "message_handler.hh"
#include "log.hh" #include "log.hh"
#include "match.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "project.hh" #include "project.hh"
#include "query_utils.hh" #include "query_utils.hh"
@ -263,7 +262,7 @@ void EmitSemanticHighlight(DB *db, WorkingFile *wfile, QueryFile &file) {
g_config->highlight.blacklist); g_config->highlight.blacklist);
assert(file.def); assert(file.def);
if (wfile->buffer_content.size() > g_config->highlight.largeFileSize || if (wfile->buffer_content.size() > g_config->highlight.largeFileSize ||
!match.IsMatch(file.def->path)) !match.Matches(file.def->path))
return; return;
// Group symbols together. // Group symbols together.

View File

@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0 // SPDX-License-Identifier: Apache-2.0
#include "clang_complete.hh" #include "clang_complete.hh"
#include "match.hh"
#include "message_handler.hh" #include "message_handler.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "project.hh" #include "project.hh"

View File

@ -8,7 +8,6 @@
#include "include_complete.hh" #include "include_complete.hh"
#include "log.hh" #include "log.hh"
#include "lsp.hh" #include "lsp.hh"
#include "match.hh"
#include "message_handler.hh" #include "message_handler.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
@ -187,7 +186,7 @@ bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles,
return false; return false;
} }
if (!matcher.IsMatch(request.path)) { if (!matcher.Matches(request.path)) {
LOG_IF_S(INFO, loud) << "skip " << request.path; LOG_IF_S(INFO, loud) << "skip " << request.path;
return false; return false;
} }
@ -309,7 +308,7 @@ bool Indexer_Parse(CompletionManager *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.IsMatch(path)) { if (!matcher.Matches(path)) {
LOG_IF_S(INFO, loud) << "skip index for " << path; LOG_IF_S(INFO, loud) << "skip index for " << path;
continue; continue;
} }

View File

@ -6,7 +6,6 @@
#include "clang_tu.hh" // llvm::vfs #include "clang_tu.hh" // llvm::vfs
#include "filesystem.hh" #include "filesystem.hh"
#include "log.hh" #include "log.hh"
#include "match.hh"
#include "pipeline.hh" #include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
#include "serializers/json.hh" #include "serializers/json.hh"
@ -485,8 +484,8 @@ void Project::Index(WorkingFiles *wfiles, RequestId id) {
int i = 0; int i = 0;
for (const Project::Entry &entry : folder.entries) { for (const Project::Entry &entry : folder.entries) {
std::string reason; std::string reason;
if (match.IsMatch(entry.filename, &reason) && if (match.Matches(entry.filename, &reason) &&
match_i.IsMatch(entry.filename, &reason)) { match_i.Matches(entry.filename, &reason)) {
bool interactive = bool interactive =
wfiles->GetFileByFilename(entry.filename) != nullptr; wfiles->GetFileByFilename(entry.filename) != nullptr;
pipeline::Index( pipeline::Index(

View File

@ -4,6 +4,8 @@
#include "utils.hh" #include "utils.hh"
#include "log.hh" #include "log.hh"
#include "message_handler.hh"
#include "pipeline.hh"
#include "platform.hh" #include "platform.hh"
#include <siphash.h> #include <siphash.h>
@ -18,10 +20,67 @@ using namespace llvm;
#include <ctype.h> #include <ctype.h>
#include <errno.h> #include <errno.h>
#include <functional> #include <functional>
#include <regex>
#include <string.h> #include <string.h>
#include <unordered_map> #include <unordered_map>
namespace ccls { namespace ccls {
struct Matcher::Impl {
std::regex regex;
};
Matcher::Matcher(const std::string &pattern)
: impl(std::make_unique<Impl>()), pattern(pattern) {
impl->regex = std::regex(pattern, std::regex_constants::ECMAScript |
std::regex_constants::icase |
std::regex_constants::optimize);
}
Matcher::~Matcher() {}
bool Matcher::Matches(const std::string &text) const {
return std::regex_search(text, impl->regex, std::regex_constants::match_any);
}
GroupMatch::GroupMatch(const std::vector<std::string> &whitelist,
const std::vector<std::string> &blacklist) {
auto err = [](const std::string &pattern, const char *what) {
ShowMessageParam params;
params.type = MessageType::Error;
params.message =
"failed to parse EMCAScript regex " + pattern + " : " + what;
pipeline::Notify(window_showMessage, params);
};
for (const std::string &pattern : whitelist) {
try {
this->whitelist.emplace_back(pattern);
} catch (const std::exception &e) {
err(pattern, e.what());
}
}
for (const std::string &pattern : blacklist) {
try {
this->blacklist.emplace_back(pattern);
} catch (const std::exception &e) {
err(pattern, e.what());
}
}
}
bool GroupMatch::Matches(const std::string &text,
std::string *blacklist_pattern) const {
for (const Matcher &m : whitelist)
if (m.Matches(text))
return true;
for (const Matcher &m : blacklist)
if (m.Matches(text)) {
if (blacklist_pattern)
*blacklist_pattern = m.pattern;
return false;
}
return true;
}
uint64_t HashUsr(llvm::StringRef s) { uint64_t HashUsr(llvm::StringRef s) {
union { union {
uint64_t ret; uint64_t ret;

View File

@ -7,6 +7,7 @@
#include <string_view> #include <string_view>
#include <iterator> #include <iterator>
#include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
@ -15,6 +16,26 @@ class StringRef;
} }
namespace ccls { namespace ccls {
struct Matcher {
struct Impl;
std::unique_ptr<Impl> impl;
std::string pattern;
Matcher(const std::string &pattern); // throw
Matcher(Matcher&&) = default;
~Matcher();
bool Matches(const std::string &text) const;
};
struct GroupMatch {
std::vector<Matcher> whitelist, blacklist;
GroupMatch(const std::vector<std::string> &whitelist,
const std::vector<std::string> &blacklist);
bool Matches(const std::string &text,
std::string *blacklist_pattern = nullptr) const;
};
uint64_t HashUsr(llvm::StringRef s); uint64_t HashUsr(llvm::StringRef s);
std::string LowerPathIfInsensitive(const std::string &path); std::string LowerPathIfInsensitive(const std::string &path);