From 8bdce31789a60a3d16d92625ff6366c4b50f0281 Mon Sep 17 00:00:00 2001 From: romix Date: Wed, 27 Dec 2017 15:49:26 -0800 Subject: [PATCH] Produce detailed function signatures which include parameter names --- src/indexer.cc | 137 +++++++++++++----- tests/constructors/make_functions.cc | 4 +- .../func_associated_function_params.cc | 2 +- tests/function_declaration.cc | 2 +- tests/namespaces/function_declaration.cc | 2 +- tests/namespaces/namespace_reference.cc | 2 +- tests/operators/operator.cc | 2 +- tests/outline/outline2.cc | 2 +- tests/outline/static_function_in_type.cc | 2 +- .../usage/func_called_from_macro_argument.cc | 2 +- tests/usage/func_called_implicit_ctor.cc | 2 +- tests/usage/type_usage_declare_param.cc | 2 +- .../type_usage_declare_param_prototype.cc | 2 +- tests/usage/type_usage_declare_qualifiers.cc | 2 +- tests/usage/usage_inside_of_call.cc | 2 +- tests/usage/usage_inside_of_call_simple.cc | 2 +- tests/usage/var_usage_func_parameter.cc | 2 +- tests/usage/var_usage_shadowed_parameter.cc | 2 +- tests/vars/function_param.cc | 2 +- tests/vars/function_shadow_param.cc | 2 +- 20 files changed, 123 insertions(+), 54 deletions(-) diff --git a/src/indexer.cc b/src/indexer.cc index c5436ac5..dd5dea09 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -1072,6 +1072,108 @@ ClangCursor::VisitResult TemplateVisitor(ClangCursor cursor, } // namespace +// Build a detailed function signature, including argument names. +static std::string get_function_signature(IndexFile* db, + NamespaceHelper* ns, + const CXIdxDeclInfo* decl) { + // Build the function name, with scope and parameters + ClangCursor decl_cursor = decl->cursor; + std::string type_desc = decl_cursor.get_type_description(); + int args_num = clang_Cursor_getNumArguments(decl->cursor); + std::string function_name = + ns->QualifiedName(decl->semanticContainer, decl->entityInfo->name); + + std::vector arg_names; + for (int i = 0; i < args_num; i++) { + CXCursor arg = clang_Cursor_getArgument(decl->cursor, i); + auto id = ::ToString(clang_getCursorDisplayName(arg)); + arg_names.push_back(id); + } + + if (clang_Cursor_isVariadic(decl->cursor)) { + arg_names.push_back(""); + args_num++; + } + + size_t balance = 0, offset; + size_t closing_bracket_offset = 0; + + // Scan the function type backwards. + + // First pass: find the position of the closing bracket in the type. + for (offset = type_desc.size(); offset;) { + offset--; + // Remember that ) was seen. + if (type_desc[offset] == ')') { + balance++; + if (balance == 1) { + closing_bracket_offset = offset; + } + } + // Balanced paren pair that may appear before the paren enclosing + // function parameters, see clang/lib/AST/TypePrinter.cpp + else if (type_desc[offset] == '(' && --balance == 0 && + !((offset >= 5 && !type_desc.compare(offset - 5, 5, "throw")) || + (offset >= 6 && !type_desc.compare(offset - 6, 6, "typeof")) || + (offset >= 7 && !type_desc.compare(offset - 7, 7, "_Atomic")) || + (offset >= 8 && !type_desc.compare(offset - 8, 8, "decltype")) || + (offset >= 8 && !type_desc.compare(offset - 8, 8, "noexcept")) || + (offset >= 13 && + !type_desc.compare(offset - 13, 13, "__attribute__")))) + 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--; + } + + balance = 1; + // Second pass: Insert argument names before each comma. + for (offset = closing_bracket_offset; + offset >= function_name_offset && args_num > 0;) { + offset--; + // Remember that ) was seen. + if (type_desc[offset] == ')' || type_desc[offset] == '>' || + type_desc[offset] == ']' || type_desc[offset] == '}') { + balance++; + } else if (type_desc[offset] == ',' && balance == 1) { + if (!arg_names[arg_idx].empty()) { + type_desc.insert(offset, arg_names[arg_idx]); + // Insert a space between the type and the argument name if required. + 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; + } + } + if (function_name_offset > 0) { + type_desc.insert(function_name_offset, function_name); + } else { + type_desc.append(" " + function_name); + } + + return type_desc; +} + void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { if (!kIndexStdDeclarations && clang_Location_isInSystemHeader( @@ -1310,40 +1412,7 @@ void OnIndexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { // Build detailed name. The type desc looks like void (void *). We // insert the qualified name before the first '('. - std::string qualified_name = - ns->QualifiedName(decl->semanticContainer, func->def.short_name); - std::string type_desc = decl_cursor.get_type_description(); - { - size_t balance = 0, offset; - for (offset = type_desc.size(); offset;) { - offset--; - if (type_desc[offset] == ')') - balance++; - // Balanced paren pair that may appear before the paren enclosing - // function parameters, see clang/lib/AST/TypePrinter.cpp - else if (type_desc[offset] == '(' && --balance == 0 && - !((offset >= 5 && - !type_desc.compare(offset - 5, 5, "throw")) || - (offset >= 6 && - !type_desc.compare(offset - 6, 6, "typeof")) || - (offset >= 7 && - !type_desc.compare(offset - 7, 7, "_Atomic")) || - (offset >= 8 && - !type_desc.compare(offset - 8, 8, "decltype")) || - (offset >= 8 && - !type_desc.compare(offset - 8, 8, "noexcept")) || - (offset >= 13 && - !type_desc.compare(offset - 13, 13, "__attribute__")))) - break; - } - if (offset > 0) { - type_desc.insert(offset, qualified_name); - func->def.detailed_name = type_desc; - } else { - // type_desc is probably the name of a typedef. - func->def.detailed_name = type_desc + " " + qualified_name; - } - } + func->def.detailed_name = get_function_signature(db, ns, decl); // CXCursor_OverloadedDeclRef in templates are not processed by // OnIndexReference, thus we use TemplateVisitor to collect function diff --git a/tests/constructors/make_functions.cc b/tests/constructors/make_functions.cc index 7aeb27f2..86e1970c 100644 --- a/tests/constructors/make_functions.cc +++ b/tests/constructors/make_functions.cc @@ -205,7 +205,7 @@ OUTPUT: make_functions.cc "is_operator": false, "usr": "c:@FT@>2#T#pTMakeUnique#P&&t0.1#*t0.0#", "short_name": "MakeUnique", - "detailed_name": "T *MakeUnique(Args &&...)", + "detailed_name": "T *MakeUnique(Args &&... args)", "declarations": [], "definition_spelling": "4:4-4:14", "definition_extent": "4:1-6:2", @@ -219,7 +219,7 @@ OUTPUT: make_functions.cc "is_operator": false, "usr": "c:@FT@>2#T#pTmaKE_NoRefs#Pt0.1#*t0.0#", "short_name": "maKE_NoRefs", - "detailed_name": "T *maKE_NoRefs(Args...)", + "detailed_name": "T *maKE_NoRefs(Args... args)", "declarations": [], "definition_spelling": "9:4-9:15", "definition_extent": "9:1-11:2", diff --git a/tests/declaration_vs_definition/func_associated_function_params.cc b/tests/declaration_vs_definition/func_associated_function_params.cc index 47dcdd93..2e4ddb20 100644 --- a/tests/declaration_vs_definition/func_associated_function_params.cc +++ b/tests/declaration_vs_definition/func_associated_function_params.cc @@ -15,7 +15,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#I#I#", "short_name": "foo", - "detailed_name": "int foo(int, int)", + "detailed_name": "int foo(int a, int b)", "declarations": [{ "spelling": "1:5-1:8", "extent": "1:1-1:18", diff --git a/tests/function_declaration.cc b/tests/function_declaration.cc index 42a79bda..072aa377 100644 --- a/tests/function_declaration.cc +++ b/tests/function_declaration.cc @@ -11,7 +11,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#I#I#", "short_name": "foo", - "detailed_name": "void foo(int, int)", + "detailed_name": "void foo(int a, int b)", "declarations": [{ "spelling": "1:6-1:9", "extent": "1:1-1:23", diff --git a/tests/namespaces/function_declaration.cc b/tests/namespaces/function_declaration.cc index d1e1afa2..b168b017 100644 --- a/tests/namespaces/function_declaration.cc +++ b/tests/namespaces/function_declaration.cc @@ -13,7 +13,7 @@ OUTPUT: "is_operator": false, "usr": "c:@N@hello@F@foo#I#I#", "short_name": "foo", - "detailed_name": "void hello::foo(int, int)", + "detailed_name": "void hello::foo(int a, int b)", "declarations": [{ "spelling": "2:6-2:9", "extent": "2:1-2:23", diff --git a/tests/namespaces/namespace_reference.cc b/tests/namespaces/namespace_reference.cc index 8026faf4..1e78a438 100644 --- a/tests/namespaces/namespace_reference.cc +++ b/tests/namespaces/namespace_reference.cc @@ -20,7 +20,7 @@ OUTPUT: "is_operator": false, "usr": "c:@N@ns@F@Accept#I#", "short_name": "Accept", - "detailed_name": "void ns::Accept(int)", + "detailed_name": "void ns::Accept(int a)", "declarations": [], "definition_spelling": "3:8-3:14", "definition_extent": "3:3-3:24", diff --git a/tests/operators/operator.cc b/tests/operators/operator.cc index f1f62820..f91f75d5 100644 --- a/tests/operators/operator.cc +++ b/tests/operators/operator.cc @@ -64,7 +64,7 @@ OUTPUT: "is_operator": true, "usr": "c:@S@Foo@F@operator()#I#I#", "short_name": "operator()", - "detailed_name": "int Foo::operator()(int, int)", + "detailed_name": "int Foo::operator()(int a, int b)", "declarations": [{ "spelling": "4:7-4:17", "extent": "4:3-4:31", diff --git a/tests/outline/outline2.cc b/tests/outline/outline2.cc index 8e2d11d1..d6710e55 100644 --- a/tests/outline/outline2.cc +++ b/tests/outline/outline2.cc @@ -73,7 +73,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@LoadCompilationEntriesFromDirectory#&1$@N@std@S@basic_string>#C#$@N@std@S@char_traits>#C#$@N@std@S@allocator>#C#", "short_name": "LoadCompilationEntriesFromDirectory", - "detailed_name": "std::vector LoadCompilationEntriesFromDirectory(const std::string &)", + "detailed_name": "std::vector LoadCompilationEntriesFromDirectory(const std::string &project_directory)", "declarations": [{ "spelling": "12:31-12:66", "extent": "12:1-12:104", diff --git a/tests/outline/static_function_in_type.cc b/tests/outline/static_function_in_type.cc index 7e9e6cd9..b047ca96 100644 --- a/tests/outline/static_function_in_type.cc +++ b/tests/outline/static_function_in_type.cc @@ -96,7 +96,7 @@ OUTPUT: static_function_in_type.cc "is_operator": false, "usr": "c:@N@ns@S@Foo@F@Register#*$@N@ns@S@Manager#S", "short_name": "Register", - "detailed_name": "void ns::Foo::Register(ns::Manager *)", + "detailed_name": "void ns::Foo::Register(ns::Manager *m)", "declarations": [], "definition_spelling": "5:11-5:19", "definition_extent": "5:1-6:2", diff --git a/tests/usage/func_called_from_macro_argument.cc b/tests/usage/func_called_from_macro_argument.cc index b394b9ce..185ec5da 100644 --- a/tests/usage/func_called_from_macro_argument.cc +++ b/tests/usage/func_called_from_macro_argument.cc @@ -17,7 +17,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@called#b#b#", "short_name": "called", - "detailed_name": "bool called(bool, bool)", + "detailed_name": "bool called(bool a, bool b)", "declarations": [{ "spelling": "3:6-3:12", "extent": "3:1-3:28", diff --git a/tests/usage/func_called_implicit_ctor.cc b/tests/usage/func_called_implicit_ctor.cc index 06666c2c..1e860f51 100644 --- a/tests/usage/func_called_implicit_ctor.cc +++ b/tests/usage/func_called_implicit_ctor.cc @@ -33,7 +33,7 @@ OUTPUT: "is_operator": false, "usr": "c:@S@Wrapper@F@Wrapper#I#", "short_name": "Wrapper", - "detailed_name": "void Wrapper::Wrapper(int)", + "detailed_name": "void Wrapper::Wrapper(int i)", "declarations": [{ "spelling": "2:3-2:10", "extent": "2:3-2:17", diff --git a/tests/usage/type_usage_declare_param.cc b/tests/usage/type_usage_declare_param.cc index 2b43906c..3239fe75 100644 --- a/tests/usage/type_usage_declare_param.cc +++ b/tests/usage/type_usage_declare_param.cc @@ -40,7 +40,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#*$@S@ForwardType#$@S@ImplementedType#", "short_name": "foo", - "detailed_name": "void foo(ForwardType *, ImplementedType)", + "detailed_name": "void foo(ForwardType *f, ImplementedType a)", "declarations": [], "definition_spelling": "4:6-4:9", "definition_extent": "4:1-4:47", diff --git a/tests/usage/type_usage_declare_param_prototype.cc b/tests/usage/type_usage_declare_param_prototype.cc index e19880f8..a43b3577 100644 --- a/tests/usage/type_usage_declare_param_prototype.cc +++ b/tests/usage/type_usage_declare_param_prototype.cc @@ -31,7 +31,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#*$@S@Foo#S0_#", "short_name": "foo", - "detailed_name": "void foo(Foo *, Foo *)", + "detailed_name": "void foo(Foo *f, Foo *)", "declarations": [{ "spelling": "3:6-3:9", "extent": "3:1-3:23", diff --git a/tests/usage/type_usage_declare_qualifiers.cc b/tests/usage/type_usage_declare_qualifiers.cc index 8234e1c4..0fe022cf 100644 --- a/tests/usage/type_usage_declare_qualifiers.cc +++ b/tests/usage/type_usage_declare_qualifiers.cc @@ -31,7 +31,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#&$@S@Type#&1S1_#", "short_name": "foo", - "detailed_name": "void foo(Type &, const Type &)", + "detailed_name": "void foo(Type &a0, const Type &a1)", "declarations": [], "definition_spelling": "3:6-3:9", "definition_extent": "3:1-8:2", diff --git a/tests/usage/usage_inside_of_call.cc b/tests/usage/usage_inside_of_call.cc index ee93e7ac..81925e78 100644 --- a/tests/usage/usage_inside_of_call.cc +++ b/tests/usage/usage_inside_of_call.cc @@ -39,7 +39,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@called#I#", "short_name": "called", - "detailed_name": "void called(int)", + "detailed_name": "void called(int a)", "declarations": [{ "spelling": "1:6-1:12", "extent": "1:1-1:19", diff --git a/tests/usage/usage_inside_of_call_simple.cc b/tests/usage/usage_inside_of_call_simple.cc index 3e883bbd..2044a6c2 100644 --- a/tests/usage/usage_inside_of_call_simple.cc +++ b/tests/usage/usage_inside_of_call_simple.cc @@ -17,7 +17,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@called#I#", "short_name": "called", - "detailed_name": "void called(int)", + "detailed_name": "void called(int a)", "declarations": [{ "spelling": "1:6-1:12", "extent": "1:1-1:19", diff --git a/tests/usage/var_usage_func_parameter.cc b/tests/usage/var_usage_func_parameter.cc index 6f468d7e..9ed35601 100644 --- a/tests/usage/var_usage_func_parameter.cc +++ b/tests/usage/var_usage_func_parameter.cc @@ -12,7 +12,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#I#", "short_name": "foo", - "detailed_name": "void foo(int)", + "detailed_name": "void foo(int a)", "declarations": [], "definition_spelling": "1:6-1:9", "definition_extent": "1:1-3:2", diff --git a/tests/usage/var_usage_shadowed_parameter.cc b/tests/usage/var_usage_shadowed_parameter.cc index cde0da98..bc4e938d 100644 --- a/tests/usage/var_usage_shadowed_parameter.cc +++ b/tests/usage/var_usage_shadowed_parameter.cc @@ -18,7 +18,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#I#", "short_name": "foo", - "detailed_name": "void foo(int)", + "detailed_name": "void foo(int a)", "declarations": [], "definition_spelling": "1:6-1:9", "definition_extent": "1:1-8:2", diff --git a/tests/vars/function_param.cc b/tests/vars/function_param.cc index 73a7cfa3..6462097a 100644 --- a/tests/vars/function_param.cc +++ b/tests/vars/function_param.cc @@ -25,7 +25,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#*$@S@Foo#S0_#", "short_name": "foo", - "detailed_name": "void foo(Foo *, Foo *)", + "detailed_name": "void foo(Foo *p0, Foo *p1)", "declarations": [], "definition_spelling": "3:6-3:9", "definition_extent": "3:1-3:30", diff --git a/tests/vars/function_shadow_param.cc b/tests/vars/function_shadow_param.cc index d91d2414..5f7f36b5 100644 --- a/tests/vars/function_shadow_param.cc +++ b/tests/vars/function_shadow_param.cc @@ -12,7 +12,7 @@ OUTPUT: "is_operator": false, "usr": "c:@F@foo#I#", "short_name": "foo", - "detailed_name": "void foo(int)", + "detailed_name": "void foo(int p)", "declarations": [], "definition_spelling": "1:6-1:9", "definition_extent": "1:1-3:2",