Improved unexposed template parameter tokenization
This commit is contained in:
@@ -459,4 +459,125 @@ std::vector<common::model::template_parameter> parse_unexposed_template_params(
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
bool is_type_parameter(const std::string &t)
|
||||
{
|
||||
return t.find("type-parameter-") == 0;
|
||||
}
|
||||
|
||||
bool is_qualifier(const std::string &q)
|
||||
{
|
||||
return q == "&" || q == "&&" || q == "const&";
|
||||
}
|
||||
|
||||
bool is_bracket(const std::string &b)
|
||||
{
|
||||
return b == "(" || b == ")" || b == "[" || b == "]";
|
||||
}
|
||||
|
||||
bool is_identifier_character(char c) { return std::isalnum(c) || c == '_'; }
|
||||
|
||||
bool is_identifier(const std::string &t)
|
||||
{
|
||||
return std::isalpha(t.at(0)) &&
|
||||
std::all_of(t.begin(), t.end(),
|
||||
[](const char c) { return is_identifier_character(c); });
|
||||
}
|
||||
|
||||
bool is_keyword(const std::string &t)
|
||||
{
|
||||
static std::vector<std::string> keywords {"alignas", "alignof", "asm",
|
||||
"auto", "bool", "break", "case", "catch", "char", "char16_t",
|
||||
"char32_t", "class", "concept", "const", "constexpr", "const_cast",
|
||||
"continue", "decltype", "default", "delete", "do", "double",
|
||||
"dynamic_cast", "else", "enum", "explicit", "export", "extern", "false",
|
||||
"float", "for", "friend", "goto", "if", "inline", "int", "long",
|
||||
"mutable", "namespace", "new", "noexcept", "nullptr", "operator",
|
||||
"private", "protected", "public", "register", "reinterpret_cast",
|
||||
"return", "requires", "short", "signed", "sizeof", "static",
|
||||
"static_assert", "static_cast", "struct", "switch", "template", "this",
|
||||
"thread_local", "throw", "true", "try", "typedef", "typeid", "typename",
|
||||
"union", "unsigned", "using", "virtual", "void", "volatile", "wchar_t",
|
||||
"while"};
|
||||
|
||||
return util::contains(keywords, t);
|
||||
}
|
||||
|
||||
bool is_qualified_identifier(const std::string &t)
|
||||
{
|
||||
return std::isalpha(t.at(0)) &&
|
||||
std::all_of(t.begin(), t.end(), [](const char c) {
|
||||
return is_identifier_character(c) || c == ':';
|
||||
});
|
||||
}
|
||||
|
||||
bool is_type_token(const std::string &t)
|
||||
{
|
||||
return is_type_parameter(t) ||
|
||||
(is_identifier(t) && !is_qualifier(t) && !is_bracket(t));
|
||||
}
|
||||
|
||||
std::vector<std::string> tokenize_unexposed_template_parameter(
|
||||
const std::string &t)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
|
||||
auto spaced_out = util::split(t, " ");
|
||||
|
||||
for (const auto &word : spaced_out) {
|
||||
if (is_qualified_identifier(word)) {
|
||||
if (word != "class" && word != "templated" && word != "struct")
|
||||
result.push_back(word);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string tok;
|
||||
|
||||
for (const char c : word) {
|
||||
if (c == '(' || c == ')' || c == '[' || c == ']') {
|
||||
if (!tok.empty())
|
||||
result.push_back(tok);
|
||||
result.push_back(std::string{c});
|
||||
tok.clear();
|
||||
}
|
||||
else if (c == ':') {
|
||||
if (!tok.empty() && tok != ":") {
|
||||
result.push_back(tok);
|
||||
tok = ":";
|
||||
}
|
||||
else {
|
||||
tok += ':';
|
||||
}
|
||||
}
|
||||
else if (c == ',') {
|
||||
if (!tok.empty()) {
|
||||
result.push_back(tok);
|
||||
}
|
||||
result.push_back(",");
|
||||
tok.clear();
|
||||
}
|
||||
else if (c == '*') {
|
||||
if (!tok.empty()) {
|
||||
result.push_back(tok);
|
||||
}
|
||||
result.push_back("*");
|
||||
tok.clear();
|
||||
}
|
||||
else {
|
||||
tok += c;
|
||||
}
|
||||
}
|
||||
|
||||
tok = util::trim(tok);
|
||||
|
||||
if (!tok.empty()) {
|
||||
if (tok != "class" && tok != "typename" && word != "struct")
|
||||
result.push_back(tok);
|
||||
tok.clear();
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace clanguml::common
|
||||
|
||||
@@ -153,6 +153,9 @@ std::vector<common::model::template_parameter> parse_unexposed_template_params(
|
||||
const std::function<std::string(const std::string &)> &ns_resolve,
|
||||
int depth = 0);
|
||||
|
||||
std::vector<std::string> tokenize_unexposed_template_parameter(
|
||||
const std::string &t);
|
||||
|
||||
template <typename T, typename P, typename F>
|
||||
void if_dyn_cast(P pointer, F &&func)
|
||||
{
|
||||
@@ -164,4 +167,19 @@ void if_dyn_cast(P pointer, F &&func)
|
||||
std::forward<F>(func)(dyn_cast_value);
|
||||
}
|
||||
}
|
||||
|
||||
bool is_type_parameter(const std::string &t);
|
||||
|
||||
bool is_qualifier(const std::string &q);
|
||||
|
||||
bool is_bracket(const std::string &b);
|
||||
|
||||
bool is_identifier_character(char c);
|
||||
|
||||
bool is_identifier(const std::string &t);
|
||||
|
||||
bool is_qualified_identifier(const std::string &t);
|
||||
|
||||
bool is_type_token(const std::string &t);
|
||||
|
||||
} // namespace clanguml::common
|
||||
|
||||
@@ -113,6 +113,20 @@ int template_parameter::calculate_specialization_match(
|
||||
{
|
||||
int res{0};
|
||||
|
||||
if (qualifier() != base_template_parameter.qualifier())
|
||||
return 0;
|
||||
|
||||
if (is_template_parameter() &&
|
||||
base_template_parameter.is_template_parameter() &&
|
||||
template_params().empty() &&
|
||||
base_template_parameter.template_params().empty() &&
|
||||
is_variadic() == is_variadic() &&
|
||||
is_function_template() ==
|
||||
base_template_parameter.is_function_template() &&
|
||||
is_method_template() == base_template_parameter.is_method_template()) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto maybe_base_template_parameter_type = base_template_parameter.type();
|
||||
auto maybe_template_parameter_type = type();
|
||||
|
||||
@@ -132,6 +146,9 @@ int template_parameter::calculate_specialization_match(
|
||||
!is_function_template())
|
||||
return 0;
|
||||
|
||||
if (base_template_parameter.is_method_template() && !is_method_template())
|
||||
return 0;
|
||||
|
||||
if (!base_template_parameter.template_params().empty() &&
|
||||
!template_params().empty()) {
|
||||
auto params_match = calculate_template_params_specialization_match(
|
||||
@@ -216,10 +233,29 @@ std::string template_parameter::to_string(
|
||||
}
|
||||
|
||||
if (is_method_template()) {
|
||||
assert(template_params().size() == 2);
|
||||
assert(template_params().size() > 1);
|
||||
|
||||
return fmt::format("{} {}::*{}", template_params().at(0).name().value(),
|
||||
template_params().at(1).name().value(), method_qualifier());
|
||||
if (template_params().size() == 2) {
|
||||
return fmt::format("{} {}::*{}",
|
||||
template_params().at(0).to_string(using_namespace, relative),
|
||||
template_params().at(1).to_string(using_namespace, relative),
|
||||
qualifier());
|
||||
}
|
||||
else {
|
||||
auto it = template_params().begin();
|
||||
auto return_type = it->to_string(using_namespace, relative);
|
||||
it++;
|
||||
auto class_type = it->to_string(using_namespace, relative);
|
||||
it++;
|
||||
std::vector<std::string> args;
|
||||
|
||||
for (; it != template_params().end(); it++) {
|
||||
args.push_back(it->to_string(using_namespace, relative));
|
||||
}
|
||||
|
||||
return fmt::format("{} ({}::*)({}){}", return_type, class_type,
|
||||
fmt::join(args, ","), qualifier());
|
||||
}
|
||||
}
|
||||
|
||||
std::string res;
|
||||
@@ -271,6 +307,9 @@ std::string template_parameter::to_string(
|
||||
res += fmt::format("<{}>", fmt::join(params, ","));
|
||||
}
|
||||
|
||||
if (!qualifier().empty())
|
||||
res += " " + qualifier();
|
||||
|
||||
const auto &maybe_default_value = default_value();
|
||||
if (maybe_default_value) {
|
||||
res += "=";
|
||||
@@ -342,6 +381,12 @@ int calculate_template_params_specialization_match(
|
||||
{
|
||||
int res{0};
|
||||
|
||||
if (specialization_params.size() != template_params.size() &&
|
||||
!std::any_of(template_params.begin(), template_params.end(),
|
||||
[](const auto &t) { return t.is_variadic(); })) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!specialization_params.empty() && !template_params.empty()) {
|
||||
auto template_index{0U};
|
||||
auto arg_index{0U};
|
||||
|
||||
@@ -186,9 +186,9 @@ public:
|
||||
|
||||
bool is_method_template() const { return is_method_template_; }
|
||||
|
||||
void set_method_qualifier(const std::string &q) { method_qualifier_ = q; }
|
||||
void set_qualifier(const std::string &q) { qualifier_ = q; }
|
||||
|
||||
const std::string &method_qualifier() const { return method_qualifier_; }
|
||||
const std::string &qualifier() const { return qualifier_; }
|
||||
|
||||
private:
|
||||
template_parameter() = default;
|
||||
@@ -220,7 +220,7 @@ private:
|
||||
|
||||
bool is_method_template_{false};
|
||||
|
||||
std::string method_qualifier_;
|
||||
std::string qualifier_;
|
||||
|
||||
/// Stores optional fully qualified name of constraint for this template
|
||||
/// parameter
|
||||
|
||||
Reference in New Issue
Block a user