2017-05-21 19:51:15 +00:00
|
|
|
#include "match.h"
|
2017-04-15 01:40:01 +00:00
|
|
|
|
2017-05-22 05:54:27 +00:00
|
|
|
#include "language_server_api.h"
|
2018-01-11 02:43:01 +00:00
|
|
|
#include "queue_manager.h"
|
2017-05-22 05:54:27 +00:00
|
|
|
|
2017-04-15 01:40:01 +00:00
|
|
|
#include <doctest/doctest.h>
|
2017-05-21 21:00:48 +00:00
|
|
|
#include <iostream>
|
2017-04-15 01:40:01 +00:00
|
|
|
|
2017-05-21 21:00:48 +00:00
|
|
|
// static
|
|
|
|
optional<Matcher> Matcher::Create(const std::string& search) {
|
2017-04-16 23:52:42 +00:00
|
|
|
/*
|
2017-04-15 01:40:01 +00:00
|
|
|
std::string real_search;
|
|
|
|
real_search.reserve(search.size() * 3 + 2);
|
|
|
|
for (auto c : search) {
|
|
|
|
real_search += ".*";
|
|
|
|
real_search += c;
|
|
|
|
}
|
|
|
|
real_search += ".*";
|
2017-04-16 23:52:42 +00:00
|
|
|
*/
|
2017-04-15 01:40:01 +00:00
|
|
|
|
2017-05-21 21:00:48 +00:00
|
|
|
try {
|
|
|
|
Matcher m;
|
|
|
|
m.regex_string = search;
|
2017-09-22 01:14:57 +00:00
|
|
|
m.regex = std::regex(
|
2018-01-11 02:43:01 +00:00
|
|
|
search, std::regex_constants::ECMAScript | std::regex_constants::icase |
|
|
|
|
std::regex_constants::optimize
|
2017-09-22 01:14:57 +00:00
|
|
|
// std::regex_constants::nosubs
|
2018-01-11 02:43:01 +00:00
|
|
|
);
|
2017-05-21 21:00:48 +00:00
|
|
|
return m;
|
2017-09-22 01:14:57 +00:00
|
|
|
} catch (std::exception e) {
|
2017-05-22 05:54:27 +00:00
|
|
|
Out_ShowLogMessage out;
|
|
|
|
out.display_type = Out_ShowLogMessage::DisplayType::Show;
|
|
|
|
out.params.type = lsMessageType::Error;
|
2017-09-22 01:14:57 +00:00
|
|
|
out.params.message = "cquery: Parsing EMCAScript regex \"" + search +
|
|
|
|
"\" failed; " + e.what();
|
2017-12-24 00:25:18 +00:00
|
|
|
QueueManager::WriteStdout(IpcId::Unknown, out);
|
2017-05-21 21:00:48 +00:00
|
|
|
return nullopt;
|
|
|
|
}
|
2017-04-15 01:40:01 +00:00
|
|
|
}
|
|
|
|
|
2017-04-16 23:52:42 +00:00
|
|
|
bool Matcher::IsMatch(const std::string& value) const {
|
2017-09-22 01:14:57 +00:00
|
|
|
// std::smatch match;
|
|
|
|
// return std::regex_match(value, match, regex);
|
2018-01-27 17:29:28 +00:00
|
|
|
return std::regex_search(value, regex, std::regex_constants::match_any);
|
2017-04-15 01:40:01 +00:00
|
|
|
}
|
|
|
|
|
2017-09-22 01:14:57 +00:00
|
|
|
GroupMatch::GroupMatch(const std::vector<std::string>& whitelist,
|
|
|
|
const std::vector<std::string>& blacklist) {
|
2017-05-21 21:00:48 +00:00
|
|
|
for (const std::string& entry : whitelist) {
|
|
|
|
optional<Matcher> m = Matcher::Create(entry);
|
|
|
|
if (m)
|
|
|
|
this->whitelist.push_back(*m);
|
|
|
|
}
|
|
|
|
for (const std::string& entry : blacklist) {
|
|
|
|
optional<Matcher> m = Matcher::Create(entry);
|
|
|
|
if (m)
|
|
|
|
this->blacklist.push_back(*m);
|
|
|
|
}
|
2017-05-21 19:51:15 +00:00
|
|
|
}
|
|
|
|
|
2017-09-22 01:14:57 +00:00
|
|
|
bool GroupMatch::IsMatch(const std::string& value,
|
|
|
|
std::string* match_failure_reason) const {
|
2017-05-21 19:51:15 +00:00
|
|
|
for (const Matcher& m : whitelist) {
|
2017-10-25 01:09:02 +00:00
|
|
|
if (m.IsMatch(value))
|
|
|
|
return true;
|
2017-05-21 19:51:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
for (const Matcher& m : blacklist) {
|
|
|
|
if (m.IsMatch(value)) {
|
|
|
|
if (match_failure_reason)
|
|
|
|
*match_failure_reason = "blacklist \"" + m.regex_string + "\"";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-11-19 18:05:06 +00:00
|
|
|
TEST_SUITE("Matcher") {
|
|
|
|
TEST_CASE("sanity") {
|
|
|
|
// Matcher m("abc");
|
|
|
|
// TODO: check case
|
|
|
|
// CHECK(m.IsMatch("abc"));
|
|
|
|
// CHECK(m.IsMatch("fooabc"));
|
|
|
|
// CHECK(m.IsMatch("abc"));
|
|
|
|
// CHECK(m.IsMatch("abcfoo"));
|
|
|
|
// CHECK(m.IsMatch("11a11b11c11"));
|
|
|
|
}
|
2017-04-15 01:40:01 +00:00
|
|
|
}
|