From 1d67d1ee374eecb454596e873c88327ea110f03b Mon Sep 17 00:00:00 2001 From: Jacob Dufault Date: Sat, 27 May 2017 18:53:22 -0700 Subject: [PATCH] Add additional metadata to function declarations. --- src/indexer.cc | 67 ++++++++++++++++--- src/indexer.h | 17 +++-- src/test.cc | 6 +- tests/declaration_vs_definition/func.cc | 12 +++- .../func_associated_function_params.cc | 54 +++++++++++++++ tests/declaration_vs_definition/method.cc | 12 +++- tests/function_declaration.cc | 5 +- tests/function_declaration_definition.cc | 4 +- tests/inheritance/function_override.cc | 4 +- tests/method_declaration.cc | 4 +- tests/method_definition.cc | 14 ++-- tests/multi_file/simple_impl.cc | 4 +- tests/multi_file/static.cc | 4 +- tests/namespaces/anonymous_function.cc | 4 +- tests/namespaces/function_declaration.cc | 5 +- tests/namespaces/method_declaration.cc | 4 +- tests/namespaces/method_definition.cc | 4 +- tests/outline/outline2.cc | 5 +- .../func_specialized_template_param.cc | 5 +- .../templates/specialized_func_definition.cc | 8 ++- tests/usage/func_called_from_constructor.cc | 4 +- .../usage/func_called_from_macro_argument.cc | 5 +- tests/usage/func_called_from_template.cc | 4 +- tests/usage/func_called_implicit_ctor.cc | 5 +- tests/usage/func_usage_addr_method.cc | 4 +- tests/usage/func_usage_call_method.cc | 4 +- tests/usage/func_usage_forward_decl_func.cc | 4 +- tests/usage/func_usage_forward_decl_method.cc | 4 +- tests/usage/func_usage_template_func.cc | 5 +- ...ype_usage_as_template_parameter_complex.cc | 4 +- .../type_usage_declare_param_prototype.cc | 5 +- tests/usage/type_usage_on_return_type.cc | 25 +++++-- tests/usage/type_usage_various.cc | 4 +- tests/usage/usage_inside_of_call.cc | 9 ++- tests/usage/usage_inside_of_call_simple.cc | 5 +- tests/usage/var_usage_class_member.cc | 10 ++- tests/usage/var_usage_class_member_static.cc | 5 +- 37 files changed, 277 insertions(+), 71 deletions(-) create mode 100644 tests/declaration_vs_definition/func_associated_function_params.cc diff --git a/src/indexer.cc b/src/indexer.cc index cb5a7253..25d0d655 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -163,12 +163,12 @@ bool CanBeCalledImplicitly(CXIdxEntityKind kind) { bool CursorSpellingContainsString(CXCursor cursor, CXTranslationUnit cx_tu, std::string scanning_for) { CXSourceRange range = clang_Cursor_getSpellingNameRange(cursor, 0, 0); CXToken* tokens; - unsigned int num_tokens; + unsigned num_tokens; clang_tokenize(cx_tu, range, &tokens, &num_tokens); bool result = false; - for (size_t i = 0; i < num_tokens; ++i) { + for (unsigned i = 0; i < num_tokens; ++i) { CXString name = clang_getTokenSpelling(cx_tu, tokens[i]); if (strcmp(clang_getCString(name), scanning_for.c_str()) == 0) { result = true; @@ -181,6 +181,47 @@ bool CursorSpellingContainsString(CXCursor cursor, CXTranslationUnit cx_tu, std: return result; } +// Returns the document content for the given range. May not work perfectly +// when there are tabs instead of spaces. +std::string GetDocumentContentInRange(CXTranslationUnit cx_tu, CXSourceRange range) { + std::string result; + + CXToken* tokens; + unsigned num_tokens; + clang_tokenize(cx_tu, range, &tokens, &num_tokens); + + optional previous_token_range; + + for (unsigned i = 0; i < num_tokens; ++i) { + // Add whitespace between the previous token and this one. + Range token_range = Resolve(clang_getTokenExtent(cx_tu, tokens[i])); + if (previous_token_range) { + // Insert newlines. + int16_t line_delta = token_range.start.line - previous_token_range->end.line; + assert(line_delta >= 0); + if (line_delta > 0) { + result.append((size_t)line_delta, '\n'); + // Reset column so we insert starting padding. + previous_token_range->end.column = 0; + } + // Insert spaces. + int16_t column_delta = token_range.start.column - previous_token_range->end.column; + assert(column_delta >= 0); + result.append((size_t)column_delta, ' '); + } + previous_token_range = token_range; + + // Add token content. + CXString spelling = clang_getTokenSpelling(cx_tu, tokens[i]); + result += clang_getCString(spelling); + clang_disposeString(spelling); + } + + clang_disposeTokens(cx_tu, tokens, num_tokens); + + return result; +} + } // namespace @@ -983,6 +1024,7 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { case CXIdxEntity_CXXStaticMethod: case CXIdxEntity_CXXConversionFunction: { Range decl_spelling = ResolveSpelling(decl->cursor); + Range decl_extent = ResolveExtent(decl->cursor); clang::Cursor decl_cursor = decl->cursor; clang::Cursor decl_cursor_resolved = decl_cursor.template_specialization_to_template_definition(); @@ -1005,27 +1047,34 @@ void indexDeclaration(CXClientData client_data, const CXIdxDeclInfo* decl) { assert(!func->def.definition_spelling); assert(!func->def.definition_extent); func->def.definition_spelling = decl_spelling; - func->def.definition_extent = ResolveExtent(decl->cursor); + func->def.definition_extent = decl_extent; } else { IndexFunc::Declaration declaration; declaration.spelling = decl_spelling; + declaration.extent = decl_extent; + declaration.content = GetDocumentContentInRange(param->tu->cx_tu, clang_getCursorExtent(decl->cursor)); - /* + // Add parameters. for (clang::Cursor arg : decl_cursor.get_arguments()) { switch (arg.get_kind()) { case CXCursor_ParmDecl: { - IndexFunc::DeclarationVariable decl_var; - decl_var.content = arg.get_display_name(); // FIXME/TODO: scan actual tokens. - decl_var.spelling = ResolveSpelling(arg.cx_cursor); - declaration.vars.push_back(decl_var); + Range param_spelling = ResolveSpelling(arg.cx_cursor); + + // If the name is empty (which is common for parameters), clang + // will report a range with length 1, which is not correct. + if (param_spelling.start.column == (param_spelling.end.column - 1) && + arg.get_display_name().empty()) { + param_spelling.end.column -= 1; + } + + declaration.param_spellings.push_back(param_spelling); break; } default: break; } } - */ func->declarations.push_back(declaration); } diff --git a/src/indexer.h b/src/indexer.h index 01ed0983..efd45e86 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -316,15 +316,15 @@ struct IndexFunc { IndexFuncId id; - struct DeclarationVariable { - // Spelled name of the variable. - Range spelling; - // Full text (including type) of the variable. - std::string content; - }; struct Declaration { + // Range of only the function name. Range spelling; - std::vector vars; + // Full range of the declaration. + Range extent; + // Full text of the declaration. + std::string content; + // Location of the parameter names. + std::vector param_spellings; }; // Places the function is forward-declared. @@ -350,8 +350,7 @@ struct IndexFunc { } }; MAKE_HASHABLE(IndexFunc, t.def.usr); -MAKE_REFLECT_STRUCT(IndexFunc::DeclarationVariable, spelling, content); -MAKE_REFLECT_STRUCT(IndexFunc::Declaration, spelling, vars); +MAKE_REFLECT_STRUCT(IndexFunc::Declaration, spelling, extent, content, param_spellings); template LoadCompilationEntriesFromDirectory(const std::string &)", "declarations": [{ - "spelling": "12:31-12:66" + "spelling": "12:31-12:66", + "extent": "12:1-12:104", + "content": "std::vector LoadCompilationEntriesFromDirectory(const std::string& project_directory)", + "param_spellings": ["12:86-12:103"] }] }], "vars": [{ diff --git a/tests/templates/func_specialized_template_param.cc b/tests/templates/func_specialized_template_param.cc index ef725fd5..9e0d11c6 100644 --- a/tests/templates/func_specialized_template_param.cc +++ b/tests/templates/func_specialized_template_param.cc @@ -34,7 +34,10 @@ OUTPUT: "short_name": "Bar", "detailed_name": "void Foo::Bar(Template &)", "declarations": [{ - "spelling": "5:8-5:11" + "spelling": "5:8-5:11", + "extent": "5:3-5:30", + "content": "void Bar(Template&)", + "param_spellings": ["5:29-5:29"] }], "definition_spelling": "8:11-8:14", "definition_extent": "8:1-8:36", diff --git a/tests/templates/specialized_func_definition.cc b/tests/templates/specialized_func_definition.cc index d6eb5b91..a57a2b40 100644 --- a/tests/templates/specialized_func_definition.cc +++ b/tests/templates/specialized_func_definition.cc @@ -31,9 +31,13 @@ OUTPUT: "short_name": "Foo", "detailed_name": "void Template::Foo()", "declarations": [{ - "spelling": "3:8-3:11" + "spelling": "3:8-3:11", + "extent": "3:3-3:13", + "content": "void Foo()" }, { - "spelling": "9:22-9:25" + "spelling": "9:22-9:25", + "extent": "9:1-9:30", + "content": "void Template::Foo() {}" }], "definition_spelling": "7:19-7:22", "definition_extent": "6:1-7:24", diff --git a/tests/usage/func_called_from_constructor.cc b/tests/usage/func_called_from_constructor.cc index c704bbcc..2dc9ac29 100644 --- a/tests/usage/func_called_from_constructor.cc +++ b/tests/usage/func_called_from_constructor.cc @@ -35,7 +35,9 @@ OUTPUT: "short_name": "Foo", "detailed_name": "void Foo::Foo()", "declarations": [{ - "spelling": "4:3-4:6" + "spelling": "4:3-4:6", + "extent": "4:3-4:8", + "content": "Foo()" }], "definition_spelling": "7:6-7:9", "definition_extent": "7:1-9:2", diff --git a/tests/usage/func_called_from_macro_argument.cc b/tests/usage/func_called_from_macro_argument.cc index 03dc714b..82bae5c1 100644 --- a/tests/usage/func_called_from_macro_argument.cc +++ b/tests/usage/func_called_from_macro_argument.cc @@ -15,7 +15,10 @@ OUTPUT: "short_name": "called", "detailed_name": "bool called(bool, bool)", "declarations": [{ - "spelling": "3:6-3:12" + "spelling": "3:6-3:12", + "extent": "3:1-3:28", + "content": "bool called(bool a, bool b)", + "param_spellings": ["3:18-3:19", "3:26-3:27"] }], "callers": ["1@6:14-6:20"] }, { diff --git a/tests/usage/func_called_from_template.cc b/tests/usage/func_called_from_template.cc index 0d480304..3d859dbc 100644 --- a/tests/usage/func_called_from_template.cc +++ b/tests/usage/func_called_from_template.cc @@ -20,7 +20,9 @@ OUTPUT: "short_name": "called", "detailed_name": "void called()", "declarations": [{ - "spelling": "1:6-1:12" + "spelling": "1:6-1:12", + "extent": "1:1-1:14", + "content": "void called()" }], "callers": ["1@5:3-5:9"] }, { diff --git a/tests/usage/func_called_implicit_ctor.cc b/tests/usage/func_called_implicit_ctor.cc index 437fd191..9dd820cb 100644 --- a/tests/usage/func_called_implicit_ctor.cc +++ b/tests/usage/func_called_implicit_ctor.cc @@ -27,7 +27,10 @@ OUTPUT: "short_name": "Wrapper", "detailed_name": "void Wrapper::Wrapper(int)", "declarations": [{ - "spelling": "2:3-2:10" + "spelling": "2:3-2:10", + "extent": "2:3-2:17", + "content": "Wrapper(int i)", + "param_spellings": ["2:15-2:16"] }], "declaring_type": 0, "callers": ["~2@8:10-8:16"] diff --git a/tests/usage/func_usage_addr_method.cc b/tests/usage/func_usage_addr_method.cc index 1a1fb4a3..021e91ff 100644 --- a/tests/usage/func_usage_addr_method.cc +++ b/tests/usage/func_usage_addr_method.cc @@ -26,7 +26,9 @@ OUTPUT: "short_name": "Used", "detailed_name": "void Foo::Used()", "declarations": [{ - "spelling": "2:8-2:12" + "spelling": "2:8-2:12", + "extent": "2:3-2:14", + "content": "void Used()" }], "declaring_type": 0, "callers": ["1@6:18-6:22"] diff --git a/tests/usage/func_usage_call_method.cc b/tests/usage/func_usage_call_method.cc index 601088dd..f141c141 100644 --- a/tests/usage/func_usage_call_method.cc +++ b/tests/usage/func_usage_call_method.cc @@ -27,7 +27,9 @@ OUTPUT: "short_name": "Used", "detailed_name": "void Foo::Used()", "declarations": [{ - "spelling": "2:8-2:12" + "spelling": "2:8-2:12", + "extent": "2:3-2:14", + "content": "void Used()" }], "declaring_type": 0, "callers": ["1@7:6-7:10"] diff --git a/tests/usage/func_usage_forward_decl_func.cc b/tests/usage/func_usage_forward_decl_func.cc index 8e433ccb..d9ab35e3 100644 --- a/tests/usage/func_usage_forward_decl_func.cc +++ b/tests/usage/func_usage_forward_decl_func.cc @@ -12,7 +12,9 @@ OUTPUT: "short_name": "foo", "detailed_name": "void foo()", "declarations": [{ - "spelling": "1:6-1:9" + "spelling": "1:6-1:9", + "extent": "1:1-1:11", + "content": "void foo()" }], "callers": ["1@4:3-4:6"] }, { diff --git a/tests/usage/func_usage_forward_decl_method.cc b/tests/usage/func_usage_forward_decl_method.cc index 3f0538a8..2db6bfe1 100644 --- a/tests/usage/func_usage_forward_decl_method.cc +++ b/tests/usage/func_usage_forward_decl_method.cc @@ -26,7 +26,9 @@ OUTPUT: "short_name": "foo", "detailed_name": "void Foo::foo()", "declarations": [{ - "spelling": "2:8-2:11" + "spelling": "2:8-2:11", + "extent": "2:3-2:13", + "content": "void foo()" }], "declaring_type": 0, "callers": ["1@7:6-7:9"] diff --git a/tests/usage/func_usage_template_func.cc b/tests/usage/func_usage_template_func.cc index 5eba7686..8efd8ee0 100644 --- a/tests/usage/func_usage_template_func.cc +++ b/tests/usage/func_usage_template_func.cc @@ -15,7 +15,10 @@ OUTPUT: "short_name": "accept", "detailed_name": "void accept(T)", "declarations": [{ - "spelling": "2:6-2:12" + "spelling": "2:6-2:12", + "extent": "2:1-2:15", + "content": "void accept(T)", + "param_spellings": ["2:14-2:14"] }], "callers": ["1@5:3-5:9", "1@6:3-6:9"] }, { diff --git a/tests/usage/type_usage_as_template_parameter_complex.cc b/tests/usage/type_usage_as_template_parameter_complex.cc index 40552e0a..981d3720 100644 --- a/tests/usage/type_usage_as_template_parameter_complex.cc +++ b/tests/usage/type_usage_as_template_parameter_complex.cc @@ -132,7 +132,9 @@ OUTPUT: "short_name": "foo", "detailed_name": "unique_ptr *Foo::foo()", "declarations": [{ - "spelling": "65:23-65:26" + "spelling": "65:23-65:26", + "extent": "65:3-65:28", + "content": "unique_ptr* foo()" }], "definition_spelling": "79:26-79:29", "definition_extent": "79:1-79:51", diff --git a/tests/usage/type_usage_declare_param_prototype.cc b/tests/usage/type_usage_declare_param_prototype.cc index c955f8b6..9132cf77 100644 --- a/tests/usage/type_usage_declare_param_prototype.cc +++ b/tests/usage/type_usage_declare_param_prototype.cc @@ -23,7 +23,10 @@ OUTPUT: "short_name": "foo", "detailed_name": "void foo(Foo *, Foo *)", "declarations": [{ - "spelling": "3:6-3:9" + "spelling": "3:6-3:9", + "extent": "3:1-3:23", + "content": "void foo(Foo* f, Foo*)", + "param_spellings": ["3:15-3:16", "3:22-3:22"] }], "definition_spelling": "4:6-4:9", "definition_extent": "4:1-4:26" diff --git a/tests/usage/type_usage_on_return_type.cc b/tests/usage/type_usage_on_return_type.cc index 57c48e29..0014b963 100644 --- a/tests/usage/type_usage_on_return_type.cc +++ b/tests/usage/type_usage_on_return_type.cc @@ -40,9 +40,13 @@ OUTPUT: "short_name": "foo", "detailed_name": "Type *foo()", "declarations": [{ - "spelling": "3:7-3:10" + "spelling": "3:7-3:10", + "extent": "3:1-3:12", + "content": "Type* foo()" }, { - "spelling": "4:7-4:10" + "spelling": "4:7-4:10", + "extent": "4:1-4:12", + "content": "Type* foo()" }], "definition_spelling": "5:7-5:10", "definition_extent": "5:1-5:15" @@ -52,7 +56,10 @@ OUTPUT: "short_name": "Get", "detailed_name": "Type *Foo::Get(int)", "declarations": [{ - "spelling": "8:9-8:12" + "spelling": "8:9-8:12", + "extent": "8:3-8:17", + "content": "Type* Get(int)", + "param_spellings": ["8:16-8:16"] }], "definition_spelling": "12:12-12:15", "definition_extent": "12:1-12:23", @@ -63,7 +70,9 @@ OUTPUT: "short_name": "Empty", "detailed_name": "void Foo::Empty()", "declarations": [{ - "spelling": "9:8-9:13" + "spelling": "9:8-9:13", + "extent": "9:3-9:15", + "content": "void Empty()" }], "definition_spelling": "13:11-13:16", "definition_extent": "13:1-13:21", @@ -74,7 +83,9 @@ OUTPUT: "short_name": "external", "detailed_name": "const Type &external()", "declarations": [{ - "spelling": "15:20-15:28" + "spelling": "15:20-15:28", + "extent": "15:1-15:30", + "content": "extern const Type& external()" }] }, { "id": 4, @@ -82,7 +93,9 @@ OUTPUT: "short_name": "bar", "detailed_name": "Type *bar()", "declarations": [{ - "spelling": "17:14-17:17" + "spelling": "17:14-17:17", + "extent": "17:1-17:19", + "content": "static Type* bar()" }], "definition_spelling": "18:14-18:17", "definition_extent": "18:1-18:22" diff --git a/tests/usage/type_usage_various.cc b/tests/usage/type_usage_various.cc index 2360921e..3d606dd1 100644 --- a/tests/usage/type_usage_various.cc +++ b/tests/usage/type_usage_various.cc @@ -29,7 +29,9 @@ OUTPUT: "short_name": "make", "detailed_name": "Foo *Foo::make()", "declarations": [{ - "spelling": "2:8-2:12" + "spelling": "2:8-2:12", + "extent": "2:3-2:14", + "content": "Foo* make()" }], "definition_spelling": "5:11-5:15", "definition_extent": "5:1-8:2", diff --git a/tests/usage/usage_inside_of_call.cc b/tests/usage/usage_inside_of_call.cc index fafc5670..aa194dac 100644 --- a/tests/usage/usage_inside_of_call.cc +++ b/tests/usage/usage_inside_of_call.cc @@ -33,7 +33,10 @@ OUTPUT: "short_name": "called", "detailed_name": "void called(int)", "declarations": [{ - "spelling": "1:6-1:12" + "spelling": "1:6-1:12", + "extent": "1:1-1:19", + "content": "void called(int a)", + "param_spellings": ["1:17-1:18"] }], "callers": ["2@14:3-14:9"] }, { @@ -42,7 +45,9 @@ OUTPUT: "short_name": "gen", "detailed_name": "int gen()", "declarations": [{ - "spelling": "3:5-3:8" + "spelling": "3:5-3:8", + "extent": "3:1-3:10", + "content": "int gen()" }], "callers": ["2@14:14-14:17"] }, { diff --git a/tests/usage/usage_inside_of_call_simple.cc b/tests/usage/usage_inside_of_call_simple.cc index aa549307..22712e22 100644 --- a/tests/usage/usage_inside_of_call_simple.cc +++ b/tests/usage/usage_inside_of_call_simple.cc @@ -15,7 +15,10 @@ OUTPUT: "short_name": "called", "detailed_name": "void called(int)", "declarations": [{ - "spelling": "1:6-1:12" + "spelling": "1:6-1:12", + "extent": "1:1-1:19", + "content": "void called(int a)", + "param_spellings": ["1:17-1:18"] }], "callers": ["2@6:3-6:9"] }, { diff --git a/tests/usage/var_usage_class_member.cc b/tests/usage/var_usage_class_member.cc index a6f13a1e..fe01b9f7 100644 --- a/tests/usage/var_usage_class_member.cc +++ b/tests/usage/var_usage_class_member.cc @@ -37,7 +37,10 @@ OUTPUT: "short_name": "accept", "detailed_name": "void accept(int)", "declarations": [{ - "spelling": "7:6-7:12" + "spelling": "7:6-7:12", + "extent": "7:1-7:17", + "content": "void accept(int)", + "param_spellings": ["7:16-7:16"] }], "callers": ["2@14:3-14:9", "2@15:3-15:9", "2@17:3-17:9"] }, { @@ -46,7 +49,10 @@ OUTPUT: "short_name": "accept", "detailed_name": "void accept(int *)", "declarations": [{ - "spelling": "8:6-8:12" + "spelling": "8:6-8:12", + "extent": "8:1-8:18", + "content": "void accept(int*)", + "param_spellings": ["8:17-8:17"] }], "callers": ["2@16:3-16:9"] }, { diff --git a/tests/usage/var_usage_class_member_static.cc b/tests/usage/var_usage_class_member_static.cc index 32a179b7..73f797c6 100644 --- a/tests/usage/var_usage_class_member_static.cc +++ b/tests/usage/var_usage_class_member_static.cc @@ -26,7 +26,10 @@ OUTPUT: "short_name": "accept", "detailed_name": "void accept(int)", "declarations": [{ - "spelling": "5:6-5:12" + "spelling": "5:6-5:12", + "extent": "5:1-5:17", + "content": "void accept(int)", + "param_spellings": ["5:16-5:16"] }], "callers": ["1@8:3-8:9"] }, {