mirror of
https://github.com/MaskRay/ccls.git
synced 2025-01-19 12:05:50 +00:00
Refactor function signatures: fix infinite loop processing constructors
This commit is contained in:
parent
8bdce31789
commit
6fa08b2b90
145
src/indexer.cc
145
src/indexer.cc
@ -1070,110 +1070,109 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor,
|
|||||||
return ClangCursor::VisitResult::Continue;
|
return ClangCursor::VisitResult::Continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
// Build a detailed function signature, including argument names.
|
// Build a detailed function signature, including argument names.
|
||||||
static std::string get_function_signature(IndexFile* db,
|
std::string GetFunctionSignature(IndexFile* db,
|
||||||
NamespaceHelper* ns,
|
NamespaceHelper* ns,
|
||||||
const CXIdxDeclInfo* decl) {
|
const CXIdxDeclInfo* decl) {
|
||||||
// Build the function name, with scope and parameters
|
// Build the function name, with scope and parameters
|
||||||
ClangCursor decl_cursor = decl->cursor;
|
std::string type_desc = ClangCursor(decl->cursor).get_type_description();
|
||||||
std::string type_desc = decl_cursor.get_type_description();
|
int num_args = clang_Cursor_getNumArguments(decl->cursor);
|
||||||
int args_num = clang_Cursor_getNumArguments(decl->cursor);
|
|
||||||
std::string function_name =
|
std::string function_name =
|
||||||
ns->QualifiedName(decl->semanticContainer, decl->entityInfo->name);
|
ns->QualifiedName(decl->semanticContainer, decl->entityInfo->name);
|
||||||
|
|
||||||
std::vector<std::string> arg_names;
|
std::vector<std::pair<int, std::string>> args;
|
||||||
for (int i = 0; i < args_num; i++) {
|
for (int i = 0; i < num_args; i++) {
|
||||||
CXCursor arg = clang_Cursor_getArgument(decl->cursor, i);
|
args.emplace_back(-1, ::ToString(clang_getCursorDisplayName(
|
||||||
auto id = ::ToString(clang_getCursorDisplayName(arg));
|
clang_Cursor_getArgument(decl->cursor, i))));
|
||||||
arg_names.push_back(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (clang_Cursor_isVariadic(decl->cursor)) {
|
if (clang_Cursor_isVariadic(decl->cursor)) {
|
||||||
arg_names.push_back("");
|
args.emplace_back(-1, "");
|
||||||
args_num++;
|
num_args++;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t balance = 0, offset;
|
int function_name_offset = -1;
|
||||||
size_t closing_bracket_offset = 0;
|
|
||||||
|
|
||||||
// Scan the function type backwards.
|
// Scan the function type backwards.
|
||||||
|
|
||||||
// First pass: find the position of the closing bracket in the type.
|
// First pass: find the position of the closing bracket in the type.
|
||||||
for (offset = type_desc.size(); offset;) {
|
for (int balance = 0, i = int(type_desc.size()); i--; ) {
|
||||||
offset--;
|
if (type_desc[i] == ')')
|
||||||
// Remember that ) was seen.
|
|
||||||
if (type_desc[offset] == ')') {
|
|
||||||
balance++;
|
balance++;
|
||||||
if (balance == 1) {
|
|
||||||
closing_bracket_offset = offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Balanced paren pair that may appear before the paren enclosing
|
// Balanced paren pair that may appear before the paren enclosing
|
||||||
// function parameters, see clang/lib/AST/TypePrinter.cpp
|
// function parameters, see clang/lib/AST/TypePrinter.cpp
|
||||||
else if (type_desc[offset] == '(' && --balance == 0 &&
|
else if (type_desc[i] == '(' && --balance == 0 &&
|
||||||
!((offset >= 5 && !type_desc.compare(offset - 5, 5, "throw")) ||
|
!((i >= 5 && !type_desc.compare(i - 5, 5, "throw")) ||
|
||||||
(offset >= 6 && !type_desc.compare(offset - 6, 6, "typeof")) ||
|
(i >= 6 && !type_desc.compare(i - 6, 6, "typeof")) ||
|
||||||
(offset >= 7 && !type_desc.compare(offset - 7, 7, "_Atomic")) ||
|
(i >= 7 && !type_desc.compare(i - 7, 7, "_Atomic")) ||
|
||||||
(offset >= 8 && !type_desc.compare(offset - 8, 8, "decltype")) ||
|
(i >= 8 && !type_desc.compare(i - 8, 8, "decltype")) ||
|
||||||
(offset >= 8 && !type_desc.compare(offset - 8, 8, "noexcept")) ||
|
(i >= 8 && !type_desc.compare(i - 8, 8, "noexcept")) ||
|
||||||
(offset >= 13 &&
|
(i >= 13 &&
|
||||||
!type_desc.compare(offset - 13, 13, "__attribute__"))))
|
!type_desc.compare(i - 13, 13, "__attribute__")))) {
|
||||||
|
// Do not bother with function types which return function pointers.
|
||||||
|
if (type_desc.find("(*") >= std::string::size_type(i))
|
||||||
|
function_name_offset = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t function_name_offset = offset;
|
|
||||||
|
|
||||||
if (closing_bracket_offset > 0) {
|
|
||||||
// Insert the name of the last parameter right before the closing bracket.
|
|
||||||
int arg_idx = args_num - 1;
|
|
||||||
if (args_num > 0) {
|
|
||||||
if (!arg_names[arg_idx].empty()) {
|
|
||||||
type_desc.insert(closing_bracket_offset, arg_names[arg_idx]);
|
|
||||||
// Insert a space between the type and the argument name if required.
|
|
||||||
if (!isspace(type_desc[closing_bracket_offset - 1]) &&
|
|
||||||
type_desc[closing_bracket_offset - 1] != '*' &&
|
|
||||||
type_desc[closing_bracket_offset - 1] != '&')
|
|
||||||
type_desc.insert(closing_bracket_offset, " ");
|
|
||||||
}
|
|
||||||
arg_idx--;
|
|
||||||
}
|
}
|
||||||
|
//volatile int z=0;while(!z)asm("pause");
|
||||||
|
|
||||||
balance = 1;
|
if (function_name_offset >= 0) {
|
||||||
// Second pass: Insert argument names before each comma.
|
if (num_args > 0) {
|
||||||
for (offset = closing_bracket_offset;
|
// Find positions to insert argument names.
|
||||||
offset >= function_name_offset && args_num > 0;) {
|
// Last argument name is before ')'
|
||||||
offset--;
|
num_args = 0;
|
||||||
// Remember that ) was seen.
|
// Other argument names come before ','
|
||||||
if (type_desc[offset] == ')' || type_desc[offset] == '>' ||
|
for (int balance = 0, i = function_name_offset;
|
||||||
type_desc[offset] == ']' || type_desc[offset] == '}') {
|
i < int(type_desc.size()) && num_args < int(args.size()); i++) {
|
||||||
|
if (type_desc[i] == '(' || type_desc[i] == '<' || type_desc[i] == '[')
|
||||||
balance++;
|
balance++;
|
||||||
} else if (type_desc[offset] == ',' && balance == 1) {
|
else if (type_desc[i] == ')' || type_desc[i] == '>' ||
|
||||||
if (!arg_names[arg_idx].empty()) {
|
type_desc[i] == ']') {
|
||||||
type_desc.insert(offset, arg_names[arg_idx]);
|
if (--balance <= 0) {
|
||||||
// Insert a space between the type and the argument name if required.
|
args[num_args].first = i;
|
||||||
if (!isspace(type_desc[offset - 1]) && type_desc[offset - 1] != '*' &&
|
|
||||||
type_desc[offset - 1] != '&')
|
|
||||||
type_desc.insert(offset, " ");
|
|
||||||
}
|
|
||||||
arg_idx--;
|
|
||||||
} else if (type_desc[offset] == '<' || type_desc[offset] == '[' ||
|
|
||||||
type_desc[offset] == '{')
|
|
||||||
balance--;
|
|
||||||
else if (type_desc[offset] == '(' && --balance == 0)
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (type_desc[i] == ',' && balance == 1)
|
||||||
|
args[num_args++].first = i;
|
||||||
}
|
}
|
||||||
if (function_name_offset > 0) {
|
|
||||||
|
// Second pass: Insert argument names before each comma.
|
||||||
|
int i = 0;
|
||||||
|
std::string type_desc_with_names;
|
||||||
|
for (auto& arg : args) {
|
||||||
|
if (arg.first < 0) {
|
||||||
|
LOG_S(ERROR) << "When adding argument names to '" << type_desc << "', failed to detect positions to insert argument names";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (arg.second.empty()) continue;
|
||||||
|
type_desc_with_names.insert(type_desc_with_names.end(), &type_desc[i],
|
||||||
|
&type_desc[arg.first]);
|
||||||
|
i = arg.first;
|
||||||
|
if (type_desc_with_names.size() &&
|
||||||
|
(type_desc_with_names.back() != ' ' &&
|
||||||
|
type_desc_with_names.back() != '*' &&
|
||||||
|
type_desc_with_names.back() != '&'))
|
||||||
|
type_desc_with_names.push_back(' ');
|
||||||
|
type_desc_with_names.append(arg.second);
|
||||||
|
}
|
||||||
|
type_desc_with_names.insert(type_desc_with_names.end(),
|
||||||
|
type_desc.begin() + i, type_desc.end());
|
||||||
|
type_desc = std::move(type_desc_with_names);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO auto f() -> int(*)() ; int(*f())()
|
||||||
type_desc.insert(function_name_offset, function_name);
|
type_desc.insert(function_name_offset, function_name);
|
||||||
} else {
|
} else {
|
||||||
type_desc.append(" " + function_name);
|
// type_desc is either a typedef, or some complicated type we cannot handle.
|
||||||
|
// Append the function_name in this case.
|
||||||
|
type_desc.push_back(' ');
|
||||||
|
type_desc.append(function_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
return type_desc;
|
return type_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
||||||
if (!kIndexStdDeclarations &&
|
if (!kIndexStdDeclarations &&
|
||||||
clang_Location_isInSystemHeader(
|
clang_Location_isInSystemHeader(
|
||||||
@ -1412,7 +1411,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) {
|
|||||||
|
|
||||||
// Build detailed name. The type desc looks like void (void *). We
|
// Build detailed name. The type desc looks like void (void *). We
|
||||||
// insert the qualified name before the first '('.
|
// insert the qualified name before the first '('.
|
||||||
func->def.detailed_name = get_function_signature(db, ns, decl);
|
func->def.detailed_name = GetFunctionSignature(db, ns, decl);
|
||||||
|
|
||||||
// CXCursor_OverloadedDeclRef in templates are not processed by
|
// CXCursor_OverloadedDeclRef in templates are not processed by
|
||||||
// OnIndexReference, thus we use TemplateVisitor to collect function
|
// OnIndexReference, thus we use TemplateVisitor to collect function
|
||||||
|
Loading…
Reference in New Issue
Block a user