in watchman/query/parse.cpp [332:460]
std::shared_ptr<Query> parseQueryLegacy(
const std::shared_ptr<Root>& root,
const json_ref& args,
int start,
uint32_t* next_arg,
const char* clockspec,
json_ref* expr_p) {
bool include = true;
bool negated = false;
uint32_t i;
const char* term_name = "match";
json_ref included, excluded;
auto query_obj = json_object();
if (!args.isArray()) {
throw QueryParseError("Expected an array");
}
for (i = start; i < json_array_size(args); i++) {
const char* arg = json_string_value(json_array_get(args, i));
if (!arg) {
/* not a string value! */
throw QueryParseError(folly::to<std::string>(
"rule @ position ", i, " is not a string value"));
}
}
for (i = start; i < json_array_size(args); i++) {
const char* arg = json_string_value(json_array_get(args, i));
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!strcmp(arg, "-X")) {
include = false;
continue;
}
if (!strcmp(arg, "-I")) {
include = true;
continue;
}
if (!strcmp(arg, "!")) {
negated = true;
continue;
}
if (!strcmp(arg, "-P")) {
term_name = "ipcre";
continue;
}
if (!strcmp(arg, "-p")) {
term_name = "pcre";
continue;
}
// Which group are we going to file it into
json_ref container;
if (include) {
if (!included) {
included =
json_array({typed_string_to_json("anyof", W_STRING_UNICODE)});
}
container = included;
} else {
if (!excluded) {
excluded =
json_array({typed_string_to_json("anyof", W_STRING_UNICODE)});
}
container = excluded;
}
auto term = json_array(
{typed_string_to_json(term_name, W_STRING_UNICODE),
typed_string_to_json(arg),
typed_string_to_json("wholename", W_STRING_UNICODE)});
if (negated) {
term = json_array({typed_string_to_json("not", W_STRING_UNICODE), term});
}
json_array_append_new(container, std::move(term));
// Reset negated flag
negated = false;
term_name = "match";
}
if (excluded) {
excluded =
json_array({typed_string_to_json("not", W_STRING_UNICODE), excluded});
}
json_ref query_array;
if (included && excluded) {
query_array = json_array(
{typed_string_to_json("allof", W_STRING_UNICODE), excluded, included});
} else if (included) {
query_array = included;
} else {
query_array = excluded;
}
// query_array may be NULL, which means find me all files.
// Otherwise, it is the expression we want to use.
if (query_array) {
json_object_set_new_nocheck(
query_obj, "expression", std::move(query_array));
}
// For trigger
if (next_arg) {
*next_arg = i;
}
if (clockspec) {
json_object_set_new_nocheck(
query_obj, "since", typed_string_to_json(clockspec, W_STRING_UNICODE));
}
/* compose the query with the field list */
auto query = parseQuery(root, query_obj);
if (expr_p) {
*expr_p = query_obj;
}
if (query) {
w_query_legacy_field_list(&query->fieldList);
}
return query;
}