diff --git a/CMakeLists.txt b/CMakeLists.txt index b202db78..47af70f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -181,9 +181,7 @@ target_sources(ccls PRIVATE third_party/siphash.cc) target_sources(ccls PRIVATE src/clang_complete.cc src/clang_tu.cc - src/clang_utils.cc src/config.cc - src/file_consumer.cc src/filesystem.cc src/fuzzy_match.cc src/main.cc @@ -209,13 +207,12 @@ target_sources(ccls PRIVATE ) target_sources(ccls PRIVATE - src/messages/ccls_base.cc - src/messages/ccls_callHierarchy.cc - src/messages/ccls_callers.cc - src/messages/ccls_fileInfo.cc - src/messages/ccls_freshenIndex.cc - src/messages/ccls_inheritanceHierarchy.cc - src/messages/ccls_memberHierarchy.cc + src/messages/ccls_call.cc + src/messages/ccls_info.cc + src/messages/ccls_inheritance.cc + src/messages/ccls_member.cc + src/messages/ccls_navigate.cc + src/messages/ccls_reload.cc src/messages/ccls_vars.cc src/messages/exit.cc src/messages/initialize.cc @@ -224,10 +221,8 @@ target_sources(ccls PRIVATE src/messages/textDocument_codeLens.cc src/messages/textDocument_completion.cc src/messages/textDocument_definition.cc - src/messages/textDocument_didChange.cc - src/messages/textDocument_didClose.cc - src/messages/textDocument_didOpen.cc - src/messages/textDocument_didSave.cc + src/messages/textDocument_did.cc + src/messages/textDocument_formatting.cc src/messages/textDocument_documentHighlight.cc src/messages/textDocument_documentSymbol.cc src/messages/textDocument_hover.cc diff --git a/README.md b/README.md index 4f041e87..2a0c70fa 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,24 @@ ccls, which originates from [cquery](https://github.com/cquery-project/cquery), is a C/C++/Objective-C language server. * code completion (with both signature help and snippets) - * [definition](src/messages/text_document_definition.cc)/[references](src/messages/text_document_references.cc), and other cross references - * [call (caller/callee) hierarchy](src/messages/ccls_call_hierarchy.cc), [inheritance (base/derived) hierarchy](src/messages/ccls_inheritance_hierarchy.cc), [member hierarchy](src/messages/ccls_member_hierarchy.cc) - * [symbol rename](src/messages/text_document_rename.cc) - * [document symbols](src/messages/text_document_document_symbol.cc) and approximate search of [workspace symbol](src/messages/workspace_symbol.cc) - * [hover information](src/messages/text_document_hover.cc) - * diagnostics - * code actions (clang FixIts) - * preprocessor skipped regions - * semantic highlighting, including support for [rainbow semantic highlighting](https://medium.com/@evnbr/coding-in-color-3a6db2743a1e) + * [definition](src/messages/textDocument_definition.cc)/[references](src/messages/textDcument_references.cc), and other cross references + * cross reference extensions: `$ccls/call` `$ccls/inheritance` `$ccls/member` `$ccls/vars` ... + * formatting + * hierarchies: [call (caller/callee) hierarchy](src/messages/ccls_call.cc), [inheritance (base/derived) hierarchy](src/messages/ccls_inheritance.cc), [member hierarchy](src/messages/ccls_member.cc) + * [symbol rename](src/messages/textDocument_rename.cc) + * [document symbols](src/messages/textDocument_documentSymbol.cc) and approximate search of [workspace symbol](src/messages/workspace_symbol.cc) + * [hover information](src/messages/textDocument_hover.cc) + * diagnostics and code actions (clang FixIts) + * semantic highlighting and preprocessor skipped regions + * semantic navigation: `$ccls/navigate` -It makes use of C++17 features, has less third-party dependencies and slimmed-down code base. Cross reference features are strengthened, (see [wiki/FAQ](../../wiki/FAQ)). It currently uses libclang to index C++ code but will switch to Clang C++ API. Refactoring and formatting are non-goals as they can be provided by clang-format, clang-include-fixer and other Clang based tools. +It has a global view of the code base and support a lot of cross reference features, see [wiki/FAQ](../../wiki/FAQ). +It starts indexing the whole project (including subprojects if exist) parallelly when you open the first file, while the main thread can serve requests before the indexing is complete. +Saving files will incrementally update the index. + +Compared with cquery, it makes use of C++17 features, has less third-party dependencies and slimmed-down code base. +It leverages Clang C++ API as [clangd](https://clang.llvm.org/extra/clangd.html) does, which provides better support for code completion and diagnostics. +Refactoring is a non-goal as it can be provided by clang-include-fixer and other Clang based tools. The comparison with cquery as noted on 2018-07-15: @@ -35,4 +42,7 @@ cquery has system include path detection (through running the compiler driver) w * [Build](../../wiki/Build) * [Emacs](../../wiki/Emacs) +* [LanguageClient-neovim](../../wiki/LanguageClient-neovim) * [FAQ](../../wiki/FAQ) + +ccls can index itself (~180MiB RSS when ide, noted on 2018-09-01), FreeBSD, glibc, Linux, LLVM (~1800MiB RSS), musl (~60MiB RSS), ... with decent memory footprint. See [wiki/compile_commands.json](../../wiki/compile_commands.json) for examples. diff --git a/cmake/FindClang.cmake b/cmake/FindClang.cmake index e4286d51..e56e25dd 100644 --- a/cmake/FindClang.cmake +++ b/cmake/FindClang.cmake @@ -69,7 +69,17 @@ set(_Clang_REQUIRED_VARS Clang_LIBRARY Clang_INCLUDE_DIR Clang_EXECUTABLE LLVM_INCLUDE_DIR LLVM_BUILD_INCLUDE_DIR) _Clang_find_library(Clang_LIBRARY clangIndex) +_Clang_find_add_library(clangFormat) _Clang_find_add_library(clangTooling) + +# TODO Remove after dropping clang 6 +_Clang_find_library(clangToolingInclusions_LIBRARY clangToolingInclusions) +if (clangToolingInclusions_LIBRARY) + list(APPEND _Clang_LIBRARIES ${clangToolingInclusions_LIBRARY}) +endif() + +_Clang_find_add_library(clangToolingCore) +_Clang_find_add_library(clangRewrite) _Clang_find_add_library(clangFrontend) _Clang_find_add_library(clangParse) _Clang_find_add_library(clangSerialization) diff --git a/index_tests/_empty_test.cc b/index_tests/_empty_test.cc index d1ae7a6c..228b2674 100644 --- a/index_tests/_empty_test.cc +++ b/index_tests/_empty_test.cc @@ -1,10 +1,4 @@ /* OUTPUT: -{ - "includes": [], - "skipped_ranges": [], - "usr2func": [], - "usr2type": [], - "usr2var": [] -} +{} */ diff --git a/index_tests/class_forward_declaration.cc b/index_tests/class_forward_declaration.cc index fd80cefb..0da90161 100644 --- a/index_tests/class_forward_declaration.cc +++ b/index_tests/class_forward_declaration.cc @@ -15,9 +15,9 @@ OUTPUT: "qual_name_offset": 6, "short_name": "Foo", "kind": 5, - "declarations": ["1:7-1:10|0|1|1", "2:7-2:10|0|1|1", "4:7-4:10|0|1|1"], - "spell": "3:7-3:10|0|1|2", - "extent": "3:1-3:13|0|1|0", + "declarations": ["1:7-1:10|1:1-1:10|0|1|1|-1", "2:7-2:10|2:1-2:10|0|1|1|-1", "4:7-4:10|4:1-4:10|0|1|1|-1"], + "spell": "3:7-3:10|0|1|2|-1", + "extent": "3:1-3:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/constructors/constructor.cc b/index_tests/constructors/constructor.cc index cf764596..72fcaf0d 100644 --- a/index_tests/constructors/constructor.cc +++ b/index_tests/constructors/constructor.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "3:3-3:6|15041163540773201510|2|1026", - "extent": "3:3-3:11|15041163540773201510|2|0", + "spell": "3:3-3:6|15041163540773201510|2|1026|-1", + "extent": "3:3-3:11|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["7:7-7:8|4259594751088586730|3|16676", "8:17-8:20|4259594751088586730|3|16676"], + "uses": ["7:7-7:8|4259594751088586730|3|16676|-1", "8:17-8:20|4259594751088586730|3|16676|-1"], "callees": [] }, { "usr": 4259594751088586730, @@ -36,8 +36,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "6:6-6:9|0|1|2", - "extent": "6:1-9:2|0|1|0", + "spell": "6:6-6:9|0|1|2|-1", + "extent": "6:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [10983126130596230582, 17165811951126099095], @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [3385168158331140247], "vars": [], "instances": [10983126130596230582, 17165811951126099095], - "uses": ["3:3-3:6|15041163540773201510|2|4", "7:3-7:6|4259594751088586730|3|4", "8:3-8:6|4259594751088586730|3|4", "8:17-8:20|4259594751088586730|3|4"] + "uses": ["3:3-3:6|15041163540773201510|2|4|-1", "7:3-7:6|4259594751088586730|3|4|-1", "8:3-8:6|4259594751088586730|3|4|-1", "8:17-8:20|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 10983126130596230582, @@ -68,8 +68,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "7:7-7:8|4259594751088586730|3|2", - "extent": "7:3-7:8|4259594751088586730|3|0", + "spell": "7:7-7:8|4259594751088586730|3|2|-1", + "extent": "7:3-7:8|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, @@ -81,8 +81,8 @@ OUTPUT: "short_name": "f2", "hover": "Foo *f2 = new Foo()", "declarations": [], - "spell": "8:8-8:10|4259594751088586730|3|2", - "extent": "8:3-8:22|4259594751088586730|3|0", + "spell": "8:8-8:10|4259594751088586730|3|2|-1", + "extent": "8:3-8:22|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/constructors/destructor.cc b/index_tests/constructors/destructor.cc index f7724c3b..97207f37 100644 --- a/index_tests/constructors/destructor.cc +++ b/index_tests/constructors/destructor.cc @@ -26,12 +26,12 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "3:3-3:6|15041163540773201510|2|1026", - "extent": "3:3-3:11|15041163540773201510|2|0", + "spell": "3:3-3:6|15041163540773201510|2|1026|-1", + "extent": "3:3-3:11|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:7-8:8|4259594751088586730|3|16676"], + "uses": ["8:7-8:8|4259594751088586730|3|16676|-1"], "callees": [] }, { "usr": 4259594751088586730, @@ -41,8 +41,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:6-7:9|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:6-7:9|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [1893354193220338759], @@ -56,8 +56,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "4:3-4:4|15041163540773201510|2|1026", - "extent": "4:3-4:12|15041163540773201510|2|0", + "spell": "4:3-4:7|15041163540773201510|2|1026|-1", + "extent": "4:3-4:12|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -71,8 +71,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -80,7 +80,7 @@ OUTPUT: "funcs": [3385168158331140247, 7440261702884428359], "vars": [], "instances": [1893354193220338759], - "uses": ["3:3-3:6|15041163540773201510|2|4", "4:4-4:7|15041163540773201510|2|4", "8:3-8:6|4259594751088586730|3|4"] + "uses": ["3:3-3:6|15041163540773201510|2|4|-1", "4:4-4:7|15041163540773201510|2|4|-1", "8:3-8:6|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 1893354193220338759, @@ -88,8 +88,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "8:7-8:8|4259594751088586730|3|2", - "extent": "8:3-8:8|4259594751088586730|3|0", + "spell": "8:7-8:8|4259594751088586730|3|2|-1", + "extent": "8:3-8:8|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/constructors/implicit_constructor.cc b/index_tests/constructors/implicit_constructor.cc index be98be7f..b3995cfd 100644 --- a/index_tests/constructors/implicit_constructor.cc +++ b/index_tests/constructors/implicit_constructor.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [449111627548814328, 17097499197730163115], @@ -35,12 +35,12 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "2:3-2:7|13487927231218873822|2|1026", - "extent": "2:3-2:12|13487927231218873822|2|0", + "spell": "2:3-2:7|13487927231218873822|2|1026|-1", + "extent": "2:3-2:12|13487927231218873822|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:8-6:12|3957104924306079513|3|16676", "7:15-7:19|3957104924306079513|3|16676"], + "uses": ["6:8-6:12|3957104924306079513|3|16676|-1", "7:15-7:19|3957104924306079513|3|16676|-1"], "callees": [] }], "usr2type": [{ @@ -50,8 +50,8 @@ OUTPUT: "short_name": "Type", "kind": 23, "declarations": [], - "spell": "1:8-1:12|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:12|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [10530961286677896857], "vars": [], "instances": [449111627548814328, 17097499197730163115], - "uses": ["2:3-2:7|13487927231218873822|2|4", "6:3-6:7|3957104924306079513|3|4", "7:15-7:19|3957104924306079513|3|4"] + "uses": ["2:3-2:7|13487927231218873822|2|4|-1", "6:3-6:7|3957104924306079513|3|4|-1", "7:15-7:19|3957104924306079513|3|4|-1"] }], "usr2var": [{ "usr": 449111627548814328, @@ -67,8 +67,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "foo0", "declarations": [], - "spell": "6:8-6:12|3957104924306079513|3|2", - "extent": "6:3-6:12|3957104924306079513|3|0", + "spell": "6:8-6:12|3957104924306079513|3|2|-1", + "extent": "6:3-6:12|3957104924306079513|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -80,8 +80,8 @@ OUTPUT: "short_name": "foo1", "hover": "Type foo1 = Type()", "declarations": [], - "spell": "7:8-7:12|3957104924306079513|3|2", - "extent": "7:3-7:21|3957104924306079513|3|0", + "spell": "7:8-7:12|3957104924306079513|3|2|-1", + "extent": "7:3-7:21|3957104924306079513|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, diff --git a/index_tests/constructors/invalid_reference.cc b/index_tests/constructors/invalid_reference.cc index c6c933e1..dfb742c2 100644 --- a/index_tests/constructors/invalid_reference.cc +++ b/index_tests/constructors/invalid_reference.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "4:6-4:9|15041163540773201510|2|1026", - "extent": "4:1-4:11|15041163540773201510|2|0", + "spell": "4:6-4:9|15041163540773201510|2|1026|-1", + "extent": "4:1-4:11|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -35,8 +35,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -44,7 +44,7 @@ OUTPUT: "funcs": [17319723337446061757], "vars": [], "instances": [], - "uses": ["4:1-4:4|0|1|4", "4:6-4:9|15041163540773201510|2|4"] + "uses": ["4:1-4:4|0|1|4|-1", "4:6-4:9|15041163540773201510|2|4|-1"] }], "usr2var": [] } diff --git a/index_tests/constructors/make_functions.cc b/index_tests/constructors/make_functions.cc index e2e3be4c..c285c1d5 100644 --- a/index_tests/constructors/make_functions.cc +++ b/index_tests/constructors/make_functions.cc @@ -36,8 +36,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "7:3-7:9|14935975554338052500|2|1026", - "extent": "7:3-7:32|14935975554338052500|2|0", + "spell": "7:3-7:9|14935975554338052500|2|1026|-1", + "extent": "7:3-7:32|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -51,8 +51,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "6:3-6:9|14935975554338052500|2|1026", - "extent": "6:3-6:17|14935975554338052500|2|0", + "spell": "6:3-6:9|14935975554338052500|2|1026|-1", + "extent": "6:3-6:17|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -66,8 +66,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "5:3-5:9|14935975554338052500|2|1026", - "extent": "5:3-5:14|14935975554338052500|2|0", + "spell": "5:3-5:9|14935975554338052500|2|1026|-1", + "extent": "5:3-5:14|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -81,8 +81,8 @@ OUTPUT: make_functions.h "kind": 9, "storage": 0, "declarations": [], - "spell": "8:3-8:9|14935975554338052500|2|1026", - "extent": "8:3-8:30|14935975554338052500|2|0", + "spell": "8:3-8:9|14935975554338052500|2|1026|-1", + "extent": "8:3-8:30|14935975554338052500|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -96,8 +96,8 @@ OUTPUT: make_functions.h "short_name": "Bar", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -105,7 +105,7 @@ OUTPUT: make_functions.h "funcs": [], "vars": [], "instances": [], - "uses": ["7:17-7:20|14935975554338052500|2|4", "8:15-8:18|14935975554338052500|2|4"] + "uses": ["7:17-7:20|14935975554338052500|2|4|-1", "8:15-8:18|14935975554338052500|2|4|-1"] }, { "usr": 14935975554338052500, "detailed_name": "class Foobar {}", @@ -113,8 +113,8 @@ OUTPUT: make_functions.h "short_name": "Foobar", "kind": 5, "declarations": [], - "spell": "3:7-3:13|0|1|2", - "extent": "3:1-9:2|0|1|0", + "spell": "3:7-3:13|0|1|2|-1", + "extent": "3:1-9:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -122,7 +122,7 @@ OUTPUT: make_functions.h "funcs": [13131778807733950299, 13028995015627606181, 3765833212244435302, 17321436359755983845], "vars": [], "instances": [], - "uses": ["5:3-5:9|14935975554338052500|2|4", "6:3-6:9|14935975554338052500|2|4", "7:3-7:9|14935975554338052500|2|4", "8:3-8:9|14935975554338052500|2|4"] + "uses": ["5:3-5:9|14935975554338052500|2|4|-1", "6:3-6:9|14935975554338052500|2|4|-1", "7:3-7:9|14935975554338052500|2|4|-1", "8:3-8:9|14935975554338052500|2|4|-1"] }], "usr2var": [] } @@ -154,12 +154,12 @@ OUTPUT: make_functions.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "9:4-9:15|0|1|2", - "extent": "9:1-11:2|0|1|0", + "spell": "9:4-9:15|0|1|2|-1", + "extent": "9:1-11:2|0|1|0|-1", "bases": [], "derived": [], "vars": [3908732770590594660], - "uses": ["17:3-17:14|2816883305867289955|3|16420"], + "uses": ["17:3-17:14|2816883305867289955|3|16420|-1"], "callees": [] }, { "usr": 2816883305867289955, @@ -169,8 +169,8 @@ OUTPUT: make_functions.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "13:6-13:14|0|1|2", - "extent": "13:1-18:2|0|1|0", + "spell": "13:6-13:14|0|1|2|-1", + "extent": "13:1-18:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -210,12 +210,12 @@ OUTPUT: make_functions.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "4:4-4:14|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:4-4:14|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "bases": [], "derived": [], "vars": [8463700030555379526], - "uses": ["14:3-14:13|2816883305867289955|3|16420", "15:3-15:13|2816883305867289955|3|16420", "16:3-16:13|2816883305867289955|3|16420"], + "uses": ["14:3-14:13|2816883305867289955|3|16420|-1", "15:3-15:13|2816883305867289955|3|16420|-1", "16:3-16:13|2816883305867289955|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -262,7 +262,7 @@ OUTPUT: make_functions.cc "funcs": [], "vars": [], "instances": [], - "uses": ["16:29-16:32|2816883305867289955|3|4", "17:30-17:33|2816883305867289955|3|4"] + "uses": ["16:29-16:32|2816883305867289955|3|4|-1", "17:30-17:33|2816883305867289955|3|4|-1"] }, { "usr": 14935975554338052500, "detailed_name": "class Foobar {}", @@ -277,7 +277,7 @@ OUTPUT: make_functions.cc "funcs": [], "vars": [], "instances": [], - "uses": ["14:14-14:20|2816883305867289955|3|4", "15:14-15:20|2816883305867289955|3|4", "16:14-16:20|2816883305867289955|3|4", "17:15-17:21|2816883305867289955|3|4"] + "uses": ["14:14-14:20|2816883305867289955|3|4|-1", "15:14-15:20|2816883305867289955|3|4|-1", "16:14-16:20|2816883305867289955|3|4|-1", "17:15-17:21|2816883305867289955|3|4|-1"] }], "usr2var": [{ "usr": 180270746871803062, @@ -285,8 +285,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 4, "short_name": "args", "declarations": [], - "spell": "9:24-9:28|11363675606380070883|3|1026", - "extent": "9:16-9:28|11363675606380070883|3|0", + "spell": "9:24-9:28|11363675606380070883|3|1026|-1", + "extent": "9:16-9:28|11363675606380070883|3|0|-1", "type": 87, "uses": [], "kind": 253, @@ -297,8 +297,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 6, "short_name": "args", "declarations": [], - "spell": "4:25-4:29|768523651983844320|3|1026", - "extent": "4:15-4:29|768523651983844320|3|0", + "spell": "4:25-4:29|768523651983844320|3|1026|-1", + "extent": "4:15-4:29|768523651983844320|3|0|-1", "type": 0, "uses": [], "kind": 253, @@ -309,8 +309,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 8, "short_name": "args", "declarations": [], - "spell": "9:24-9:28|2532818908869373467|3|1026", - "extent": "9:16-9:28|2532818908869373467|3|0", + "spell": "9:24-9:28|2532818908869373467|3|1026|-1", + "extent": "9:16-9:28|2532818908869373467|3|0|-1", "type": 0, "uses": [], "kind": 253, @@ -321,8 +321,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 10, "short_name": "args", "declarations": [], - "spell": "4:25-4:29|15793662558620604611|3|1026", - "extent": "4:15-4:29|15793662558620604611|3|0", + "spell": "4:25-4:29|15793662558620604611|3|1026|-1", + "extent": "4:15-4:29|15793662558620604611|3|0|-1", "type": 0, "uses": [], "kind": 253, @@ -333,8 +333,8 @@ OUTPUT: make_functions.cc "qual_name_offset": 6, "short_name": "args", "declarations": [], - "spell": "4:25-4:29|11138976705878544996|3|1026", - "extent": "4:15-4:29|11138976705878544996|3|0", + "spell": "4:25-4:29|11138976705878544996|3|1026|-1", + "extent": "4:15-4:29|11138976705878544996|3|0|-1", "type": 0, "uses": [], "kind": 253, diff --git a/index_tests/declaration_vs_definition/class.cc b/index_tests/declaration_vs_definition/class.cc index 42a44a88..51a35677 100644 --- a/index_tests/declaration_vs_definition/class.cc +++ b/index_tests/declaration_vs_definition/class.cc @@ -17,9 +17,9 @@ OUTPUT: "qual_name_offset": 6, "short_name": "Foo", "kind": 5, - "declarations": ["1:7-1:10|0|1|1", "2:7-2:10|0|1|1", "4:7-4:10|0|1|1"], - "spell": "3:7-3:10|0|1|2", - "extent": "3:1-3:13|0|1|0", + "declarations": ["1:7-1:10|1:1-1:10|0|1|1|-1", "2:7-2:10|2:1-2:10|0|1|1|-1", "4:7-4:10|4:1-4:10|0|1|1|-1"], + "spell": "3:7-3:10|0|1|2|-1", + "extent": "3:1-3:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/declaration_vs_definition/class_member.cc b/index_tests/declaration_vs_definition/class_member.cc index a4333abc..ef14ac7b 100644 --- a/index_tests/declaration_vs_definition/class_member.cc +++ b/index_tests/declaration_vs_definition/class_member.cc @@ -30,8 +30,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -50,8 +50,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "foo", "declarations": [], - "spell": "2:7-2:10|15041163540773201510|2|1026", - "extent": "2:3-2:10|15041163540773201510|2|0", + "spell": "2:7-2:10|15041163540773201510|2|1026|-1", + "extent": "2:3-2:10|15041163540773201510|2|0|-1", "type": 53, "uses": [], "kind": 8, diff --git a/index_tests/declaration_vs_definition/class_member_static.cc b/index_tests/declaration_vs_definition/class_member_static.cc index c0ae1aa7..4655b4be 100644 --- a/index_tests/declaration_vs_definition/class_member_static.cc +++ b/index_tests/declaration_vs_definition/class_member_static.cc @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -41,16 +41,16 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["5:5-5:8|0|1|4"] + "uses": ["5:5-5:8|0|1|4|-1"] }], "usr2var": [{ "usr": 8942920329766232482, "detailed_name": "static int Foo::foo", "qual_name_offset": 11, "short_name": "foo", - "declarations": ["2:14-2:17|15041163540773201510|2|1025"], - "spell": "5:10-5:13|15041163540773201510|2|1026", - "extent": "5:1-5:13|15041163540773201510|2|0", + "declarations": ["2:14-2:17|2:3-2:17|15041163540773201510|2|1025|-1"], + "spell": "5:10-5:13|15041163540773201510|2|1026|-1", + "extent": "5:1-5:13|15041163540773201510|2|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/declaration_vs_definition/func.cc b/index_tests/declaration_vs_definition/func.cc index 718eaffa..aacda01c 100644 --- a/index_tests/declaration_vs_definition/func.cc +++ b/index_tests/declaration_vs_definition/func.cc @@ -16,9 +16,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1", "2:6-2:9|0|1|1", "4:6-4:9|0|1|1"], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-3:14|0|1|0", + "declarations": ["1:6-1:9|1:1-1:11|0|1|1|-1", "2:6-2:9|2:1-2:11|0|1|1|-1", "4:6-4:9|4:1-4:11|0|1|1|-1"], + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-3:14|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/declaration_vs_definition/func_associated_function_params.cc b/index_tests/declaration_vs_definition/func_associated_function_params.cc index a7cc5e0b..0aa1487e 100644 --- a/index_tests/declaration_vs_definition/func_associated_function_params.cc +++ b/index_tests/declaration_vs_definition/func_associated_function_params.cc @@ -16,9 +16,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:5-1:8|0|1|1", "2:5-2:8|0|1|1", "4:5-4:8|0|1|1"], - "spell": "5:5-5:8|0|1|2", - "extent": "5:1-5:36|0|1|0", + "declarations": ["1:5-1:8|1:1-1:18|0|1|1|-1", "2:5-2:8|2:1-3:16|0|1|1|-1", "4:5-4:8|4:1-4:26|0|1|1|-1"], + "spell": "5:5-5:8|0|1|2|-1", + "extent": "5:1-5:36|0|1|0|-1", "bases": [], "derived": [], "vars": [14555488990109936920, 10963664335057337329], @@ -47,8 +47,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "b", "declarations": [], - "spell": "5:20-5:21|2747674671862363334|3|1026", - "extent": "5:16-5:21|2747674671862363334|3|0", + "spell": "5:20-5:21|2747674671862363334|3|1026|-1", + "extent": "5:16-5:21|2747674671862363334|3|0|-1", "type": 53, "uses": [], "kind": 253, @@ -59,8 +59,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "5:13-5:14|2747674671862363334|3|1026", - "extent": "5:9-5:14|2747674671862363334|3|0", + "spell": "5:13-5:14|2747674671862363334|3|1026|-1", + "extent": "5:9-5:14|2747674671862363334|3|0|-1", "type": 53, "uses": [], "kind": 253, diff --git a/index_tests/declaration_vs_definition/method.cc b/index_tests/declaration_vs_definition/method.cc index 18aed73a..da2b46fb 100644 --- a/index_tests/declaration_vs_definition/method.cc +++ b/index_tests/declaration_vs_definition/method.cc @@ -18,7 +18,7 @@ OUTPUT: "short_name": "declonly", "kind": 6, "storage": 0, - "declarations": ["2:8-2:16|15041163540773201510|2|1025"], + "declarations": ["2:8-2:16|2:3-2:18|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -31,7 +31,7 @@ OUTPUT: "short_name": "purevirtual", "kind": 6, "storage": 0, - "declarations": ["3:16-3:27|15041163540773201510|2|1089"], + "declarations": ["3:16-3:27|3:3-3:33|15041163540773201510|2|1089|-1"], "bases": [], "derived": [], "vars": [], @@ -44,9 +44,9 @@ OUTPUT: "short_name": "def", "kind": 6, "storage": 0, - "declarations": ["4:8-4:11|15041163540773201510|2|1025"], - "spell": "7:11-7:14|15041163540773201510|2|1026", - "extent": "7:1-7:19|15041163540773201510|2|0", + "declarations": ["4:8-4:11|4:3-4:13|15041163540773201510|2|1025|-1"], + "spell": "7:11-7:14|15041163540773201510|2|1026|-1", + "extent": "7:1-7:19|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -60,8 +60,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -69,7 +69,7 @@ OUTPUT: "funcs": [4012226004228259562, 10939323144126021546, 15416083548883122431], "vars": [], "instances": [], - "uses": ["7:6-7:9|0|1|4"] + "uses": ["7:6-7:9|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/enums/enum_class_decl.cc b/index_tests/enums/enum_class_decl.cc index 34a1c978..a31baff5 100644 --- a/index_tests/enums/enum_class_decl.cc +++ b/index_tests/enums/enum_class_decl.cc @@ -17,8 +17,8 @@ OUTPUT: "short_name": "uint8_t", "kind": 252, "declarations": [], - "spell": "1:23-1:30|0|1|2", - "extent": "1:1-1:30|0|1|0", + "spell": "1:23-1:30|0|1|2|-1", + "extent": "1:1-1:30|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -29,13 +29,13 @@ OUTPUT: "uses": [] }, { "usr": 16985894625255407295, - "detailed_name": "enum class Foo : uint8_t {\n}", + "detailed_name": "enum class Foo : uint8_t {}", "qual_name_offset": 11, "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "2:12-2:15|0|1|2", - "extent": "2:1-5:2|0|1|0", + "spell": "2:12-2:15|0|1|2|-1", + "extent": "2:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -52,8 +52,8 @@ OUTPUT: "short_name": "A", "hover": "Foo::A = 0", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:4|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:4|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -64,8 +64,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "4:3-4:4|16985894625255407295|2|1026", - "extent": "4:3-4:9|16985894625255407295|2|0", + "spell": "4:3-4:4|16985894625255407295|2|1026|-1", + "extent": "4:3-4:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/enums/enum_decl.cc b/index_tests/enums/enum_decl.cc index 3b28d1aa..bf760444 100644 --- a/index_tests/enums/enum_decl.cc +++ b/index_tests/enums/enum_decl.cc @@ -11,13 +11,13 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 16985894625255407295, - "detailed_name": "enum Foo {\n}", + "detailed_name": "enum Foo {}", "qual_name_offset": 5, "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "A", "hover": "A = 0", "declarations": [], - "spell": "2:3-2:4|16985894625255407295|2|1026", - "extent": "2:3-2:4|16985894625255407295|2|0", + "spell": "2:3-2:4|16985894625255407295|2|1026|-1", + "extent": "2:3-2:4|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -46,8 +46,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:9|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/enums/enum_inherit.cc b/index_tests/enums/enum_inherit.cc index 195b93d9..18cb37c0 100644 --- a/index_tests/enums/enum_inherit.cc +++ b/index_tests/enums/enum_inherit.cc @@ -18,13 +18,13 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 2986879766914123941, - "detailed_name": "enum class E : int32_t {\n}", + "detailed_name": "enum class E : int32_t {}", "qual_name_offset": 11, "short_name": "E", "kind": 10, "declarations": [], - "spell": "8:12-8:13|0|1|2", - "extent": "8:1-11:2|0|1|0", + "spell": "8:12-8:13|0|1|2|-1", + "extent": "8:1-11:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -40,8 +40,8 @@ OUTPUT: "short_name": "int32_t", "kind": 252, "declarations": [], - "spell": "6:13-6:20|0|1|2", - "extent": "6:1-6:20|0|1|0", + "spell": "6:13-6:20|0|1|2|-1", + "extent": "6:1-6:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -52,13 +52,13 @@ OUTPUT: "uses": [] }, { "usr": 16985894625255407295, - "detailed_name": "enum Foo : int {\n}", + "detailed_name": "enum Foo : int {}", "qual_name_offset": 5, "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -75,8 +75,8 @@ OUTPUT: "short_name": "A", "hover": "A = 0", "declarations": [], - "spell": "2:3-2:4|16985894625255407295|2|1026", - "extent": "2:3-2:4|16985894625255407295|2|0", + "spell": "2:3-2:4|16985894625255407295|2|1026|-1", + "extent": "2:3-2:4|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -87,8 +87,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:9|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -100,8 +100,8 @@ OUTPUT: "short_name": "E0", "hover": "E::E0 = 0", "declarations": [], - "spell": "9:3-9:5|2986879766914123941|2|1026", - "extent": "9:3-9:5|2986879766914123941|2|0", + "spell": "9:3-9:5|2986879766914123941|2|1026|-1", + "extent": "9:3-9:5|2986879766914123941|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -112,8 +112,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "E20", "declarations": [], - "spell": "10:3-10:6|2986879766914123941|2|1026", - "extent": "10:3-10:11|2986879766914123941|2|0", + "spell": "10:3-10:6|2986879766914123941|2|1026|-1", + "extent": "10:3-10:11|2986879766914123941|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/enums/enum_usage.cc b/index_tests/enums/enum_usage.cc index 2d602b45..07475c77 100644 --- a/index_tests/enums/enum_usage.cc +++ b/index_tests/enums/enum_usage.cc @@ -13,13 +13,13 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 16985894625255407295, - "detailed_name": "enum class Foo : int {\n}", + "detailed_name": "enum class Foo : int {}", "qual_name_offset": 11, "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:12-1:15|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:12-1:15|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -27,7 +27,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [10677751717622394455], - "uses": ["6:1-6:4|0|1|4", "6:9-6:12|0|1|4"] + "uses": ["6:1-6:4|0|1|4|-1", "6:9-6:12|0|1|4|-1"] }], "usr2var": [{ "usr": 439339022761937396, @@ -36,10 +36,10 @@ OUTPUT: "short_name": "A", "hover": "Foo::A = 0", "declarations": [], - "spell": "2:3-2:4|16985894625255407295|2|1026", - "extent": "2:3-2:4|16985894625255407295|2|0", + "spell": "2:3-2:4|16985894625255407295|2|1026|-1", + "extent": "2:3-2:4|16985894625255407295|2|0|-1", "type": 0, - "uses": ["6:14-6:15|0|1|4"], + "uses": ["6:14-6:15|0|1|4|-1"], "kind": 22, "storage": 0 }, { @@ -49,8 +49,8 @@ OUTPUT: "short_name": "x", "hover": "Foo x = Foo::A", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:15|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:15|0|1|0|-1", "type": 16985894625255407295, "uses": [], "kind": 13, @@ -61,8 +61,8 @@ OUTPUT: "qual_name_offset": 0, "short_name": "B", "declarations": [], - "spell": "3:3-3:4|16985894625255407295|2|1026", - "extent": "3:3-3:9|16985894625255407295|2|0", + "spell": "3:3-3:4|16985894625255407295|2|1026|-1", + "extent": "3:3-3:9|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, diff --git a/index_tests/foobar.cc b/index_tests/foobar.cc index b1e571d1..4b9d2f65 100644 --- a/index_tests/foobar.cc +++ b/index_tests/foobar.cc @@ -16,13 +16,13 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 6697181287623958829, - "detailed_name": "enum A {\n}", + "detailed_name": "enum A {}", "qual_name_offset": 5, "short_name": "A", "kind": 10, "declarations": [], - "spell": "1:6-1:7|0|1|2", - "extent": "1:1-1:10|0|1|0", + "spell": "1:6-1:7|0|1|2|-1", + "extent": "1:1-1:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -30,24 +30,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:5-9:6|0|1|4"] - }, { - "usr": 7074603899792463171, - "detailed_name": "Inner", - "qual_name_offset": 0, - "short_name": "Inner", - "kind": 26, - "declarations": [], - "spell": "6:10-6:15|0|1|2", - "extent": "6:3-6:18|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [16721564935990383768], - "uses": [] + "uses": ["9:5-9:6|0|1|4|-1"] }, { "usr": 10528472276654770367, "detailed_name": "struct Foo {}", @@ -55,42 +38,25 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:8-5:11|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], "types": [13938528237873543349], "funcs": [], "vars": [], - "instances": [], - "uses": ["9:1-9:4|0|1|4", "10:1-10:4|0|1|4"] - }, { - "usr": 11976530632376795217, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "4:1-7:2|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], "instances": [12028309045033782423], - "uses": [] + "uses": ["9:1-9:4|0|1|4|-1", "10:1-10:4|0|1|4|-1"] }, { "usr": 13892793056005362145, - "detailed_name": "enum B {\n}", + "detailed_name": "enum B {}", "qual_name_offset": 5, "short_name": "B", "kind": 10, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-2:10|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-2:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -98,7 +64,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:5-10:6|0|1|4"] + "uses": ["10:5-10:6|0|1|4|-1"] }, { "usr": 13938528237873543349, "detailed_name": "struct Foo::Inner {}", @@ -106,16 +72,16 @@ OUTPUT: "short_name": "Inner", "kind": 23, "declarations": [], - "spell": "6:10-6:15|10528472276654770367|2|1026", - "extent": "6:3-6:18|10528472276654770367|2|0", + "spell": "6:10-6:15|10528472276654770367|2|1026|-1", + "extent": "6:3-6:18|10528472276654770367|2|0|-1", "alias_of": 0, "bases": [], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["9:9-9:14|0|1|4"] + "instances": [16721564935990383768], + "uses": ["9:9-9:14|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -123,9 +89,9 @@ OUTPUT: "qual_name_offset": 7, "short_name": "b", "declarations": [], - "spell": "10:8-10:9|0|1|2", - "extent": "10:1-10:9|0|1|0", - "type": 11976530632376795217, + "spell": "10:8-10:9|0|1|2|-1", + "extent": "10:1-10:9|0|1|0|-1", + "type": 10528472276654770367, "uses": [], "kind": 13, "storage": 0 @@ -135,9 +101,9 @@ OUTPUT: "qual_name_offset": 14, "short_name": "a", "declarations": [], - "spell": "9:15-9:16|0|1|2", - "extent": "9:1-9:16|0|1|0", - "type": 7074603899792463171, + "spell": "9:15-9:16|0|1|2|-1", + "extent": "9:1-9:16|0|1|0|-1", + "type": 13938528237873543349, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/function_declaration.cc b/index_tests/function_declaration.cc index 2d23e7d9..9c38f574 100644 --- a/index_tests/function_declaration.cc +++ b/index_tests/function_declaration.cc @@ -12,7 +12,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1"], + "declarations": ["1:6-1:9|1:1-1:23|0|1|1|-1"], "bases": [], "derived": [], "vars": [], diff --git a/index_tests/function_declaration_definition.cc b/index_tests/function_declaration_definition.cc index c35a6f77..1eb2ba75 100644 --- a/index_tests/function_declaration_definition.cc +++ b/index_tests/function_declaration_definition.cc @@ -14,9 +14,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1"], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-3:14|0|1|0", + "declarations": ["1:6-1:9|1:1-1:11|0|1|1|-1"], + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-3:14|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/function_definition.cc b/index_tests/function_definition.cc index 1662c48a..7ceee636 100644 --- a/index_tests/function_definition.cc +++ b/index_tests/function_definition.cc @@ -13,8 +13,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/inheritance/class_inherit.cc b/index_tests/inheritance/class_inherit.cc index e38b20bd..701b0396 100644 --- a/index_tests/inheritance/class_inherit.cc +++ b/index_tests/inheritance/class_inherit.cc @@ -14,8 +14,8 @@ OUTPUT: "short_name": "Parent", "kind": 5, "declarations": [], - "spell": "1:7-1:13|0|1|2", - "extent": "1:1-1:16|0|1|0", + "spell": "1:7-1:13|0|1|2|-1", + "extent": "1:1-1:16|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -23,7 +23,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:24-2:30|10963370434658308541|2|2052"] + "uses": ["2:24-2:30|10963370434658308541|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : public Parent {}", @@ -31,8 +31,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "2:7-2:14|0|1|2", - "extent": "2:1-2:33|0|1|0", + "spell": "2:7-2:14|0|1|2|-1", + "extent": "2:1-2:33|0|1|0|-1", "alias_of": 0, "bases": [3866412049634585509], "derived": [], diff --git a/index_tests/inheritance/class_inherit_templated_parent.cc b/index_tests/inheritance/class_inherit_templated_parent.cc index 33b80bbb..4e20cd1b 100644 --- a/index_tests/inheritance/class_inherit_templated_parent.cc +++ b/index_tests/inheritance/class_inherit_templated_parent.cc @@ -25,8 +25,8 @@ OUTPUT: "short_name": "Derived1", "kind": 5, "declarations": [], - "spell": "8:7-8:15|0|1|2", - "extent": "8:1-8:29|0|1|0", + "spell": "8:7-8:15|0|1|2|-1", + "extent": "8:1-8:29|0|1|0|-1", "alias_of": 0, "bases": [11930058224338108382], "derived": [10963370434658308541], @@ -34,7 +34,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:43-13:51|10963370434658308541|2|2052"] + "uses": ["13:43-13:51|10963370434658308541|2|2052|-1"] }, { "usr": 10651399730831737929, "detailed_name": "class Derived2 : Base2 {}", @@ -42,8 +42,8 @@ OUTPUT: "short_name": "Derived2", "kind": 5, "declarations": [], - "spell": "11:7-11:15|0|1|2", - "extent": "11:1-11:29|0|1|0", + "spell": "11:7-11:15|0|1|2|-1", + "extent": "11:1-11:29|0|1|0|-1", "alias_of": 0, "bases": [11118288764693061434], "derived": [10963370434658308541], @@ -51,7 +51,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:56-13:64|10963370434658308541|2|2052"] + "uses": ["13:56-13:64|10963370434658308541|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : Base1<3>, Base2, Derived1<4>, Derived2 {}", @@ -59,8 +59,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "13:7-13:14|0|1|2", - "extent": "13:1-13:76|0|1|0", + "spell": "13:7-13:14|0|1|2|-1", + "extent": "13:1-13:76|0|1|0|-1", "alias_of": 0, "bases": [11930058224338108382, 11118288764693061434, 5863733211528032190, 10651399730831737929], "derived": [], @@ -68,7 +68,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:33-13:40|10963370434658308541|2|2052", "13:65-13:72|10963370434658308541|2|2052"] + "uses": ["13:33-13:40|10963370434658308541|2|2052|-1", "13:65-13:72|10963370434658308541|2|2052|-1"] }, { "usr": 11118288764693061434, "detailed_name": "class Base2 {}", @@ -76,8 +76,8 @@ OUTPUT: "short_name": "Base2", "kind": 5, "declarations": [], - "spell": "5:7-5:12|0|1|2", - "extent": "5:1-5:15|0|1|0", + "spell": "5:7-5:12|0|1|2|-1", + "extent": "5:1-5:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10651399730831737929, 10963370434658308541], @@ -85,7 +85,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:27-13:32|10963370434658308541|2|2052"] + "uses": ["13:27-13:32|10963370434658308541|2|2052|-1"] }, { "usr": 11930058224338108382, "detailed_name": "class Base1 {}", @@ -93,8 +93,8 @@ OUTPUT: "short_name": "Base1", "kind": 5, "declarations": [], - "spell": "2:7-2:12|0|1|2", - "extent": "2:1-2:15|0|1|0", + "spell": "2:7-2:12|0|1|2|-1", + "extent": "2:1-2:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [5863733211528032190, 10963370434658308541], @@ -102,7 +102,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:17-13:22|10963370434658308541|2|2052"] + "uses": ["13:17-13:22|10963370434658308541|2|2052|-1"] }], "usr2var": [] } diff --git a/index_tests/inheritance/class_multiple_inherit.cc b/index_tests/inheritance/class_multiple_inherit.cc index ee1603b3..f8e171a2 100644 --- a/index_tests/inheritance/class_multiple_inherit.cc +++ b/index_tests/inheritance/class_multiple_inherit.cc @@ -16,8 +16,8 @@ OUTPUT: "short_name": "Root", "kind": 5, "declarations": [], - "spell": "1:7-1:11|0|1|2", - "extent": "1:1-1:14|0|1|0", + "spell": "1:7-1:11|0|1|2|-1", + "extent": "1:1-1:14|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [11863524815063131483, 14022569716337624303], @@ -25,7 +25,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:24-2:28|11863524815063131483|2|2052", "3:24-3:28|14022569716337624303|2|2052"] + "uses": ["2:24-2:28|11863524815063131483|2|2052|-1", "3:24-3:28|14022569716337624303|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : public MiddleA, public MiddleB {}", @@ -33,8 +33,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "4:7-4:14|0|1|2", - "extent": "4:1-4:50|0|1|0", + "spell": "4:7-4:14|0|1|2|-1", + "extent": "4:1-4:50|0|1|0|-1", "alias_of": 0, "bases": [11863524815063131483, 14022569716337624303], "derived": [], @@ -50,8 +50,8 @@ OUTPUT: "short_name": "MiddleA", "kind": 5, "declarations": [], - "spell": "2:7-2:14|0|1|2", - "extent": "2:1-2:31|0|1|0", + "spell": "2:7-2:14|0|1|2|-1", + "extent": "2:1-2:31|0|1|0|-1", "alias_of": 0, "bases": [3897841498936210886], "derived": [10963370434658308541], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:24-4:31|10963370434658308541|2|2052"] + "uses": ["4:24-4:31|10963370434658308541|2|2052|-1"] }, { "usr": 14022569716337624303, "detailed_name": "class MiddleB : public Root {}", @@ -67,8 +67,8 @@ OUTPUT: "short_name": "MiddleB", "kind": 5, "declarations": [], - "spell": "3:7-3:14|0|1|2", - "extent": "3:1-3:31|0|1|0", + "spell": "3:7-3:14|0|1|2|-1", + "extent": "3:1-3:31|0|1|0|-1", "alias_of": 0, "bases": [3897841498936210886], "derived": [10963370434658308541], @@ -76,7 +76,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:40-4:47|10963370434658308541|2|2052"] + "uses": ["4:40-4:47|10963370434658308541|2|2052|-1"] }], "usr2var": [] } diff --git a/index_tests/inheritance/function_override.cc b/index_tests/inheritance/function_override.cc index 982a2cf1..14a5661a 100644 --- a/index_tests/inheritance/function_override.cc +++ b/index_tests/inheritance/function_override.cc @@ -18,8 +18,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "5:8-5:11|10963370434658308541|2|5186", - "extent": "5:3-5:25|10963370434658308541|2|0", + "spell": "5:8-5:11|10963370434658308541|2|5186|-1", + "extent": "5:3-5:25|10963370434658308541|2|0|-1", "bases": [9948027785633571339], "derived": [], "vars": [], @@ -32,7 +32,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:16-2:19|3897841498936210886|2|1089"], + "declarations": ["2:16-2:19|2:3-2:21|3897841498936210886|2|1089|-1"], "bases": [], "derived": [6666242542855173890], "vars": [], @@ -46,8 +46,8 @@ OUTPUT: "short_name": "Root", "kind": 5, "declarations": [], - "spell": "1:7-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -55,7 +55,7 @@ OUTPUT: "funcs": [9948027785633571339], "vars": [], "instances": [], - "uses": ["4:24-4:28|10963370434658308541|2|2052"] + "uses": ["4:24-4:28|10963370434658308541|2|2052|-1"] }, { "usr": 10963370434658308541, "detailed_name": "class Derived : public Root {}", @@ -63,8 +63,8 @@ OUTPUT: "short_name": "Derived", "kind": 5, "declarations": [], - "spell": "4:7-4:14|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:7-4:14|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [3897841498936210886], "derived": [], diff --git a/index_tests/inheritance/interface_pure_virtual.cc b/index_tests/inheritance/interface_pure_virtual.cc index d002b0bd..58ee1d4f 100644 --- a/index_tests/inheritance/interface_pure_virtual.cc +++ b/index_tests/inheritance/interface_pure_virtual.cc @@ -14,7 +14,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:16-2:19|9949214233977131946|2|1089"], + "declarations": ["2:16-2:19|2:3-2:25|9949214233977131946|2|1089|-1"], "bases": [], "derived": [], "vars": [], @@ -28,8 +28,8 @@ OUTPUT: "short_name": "IFoo", "kind": 5, "declarations": [], - "spell": "1:7-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/inheritance/multiple_base_functions.cc b/index_tests/inheritance/multiple_base_functions.cc index dcc0e781..76cd27ee 100644 --- a/index_tests/inheritance/multiple_base_functions.cc +++ b/index_tests/inheritance/multiple_base_functions.cc @@ -21,8 +21,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "5:11-5:12|15826803741381445676|2|1090", - "extent": "5:3-5:23|15826803741381445676|2|0", + "spell": "5:11-5:17|15826803741381445676|2|1090|-1", + "extent": "5:3-5:23|15826803741381445676|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -36,8 +36,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "8:3-8:4|10963370434658308541|2|5186", - "extent": "8:3-8:26|10963370434658308541|2|0", + "spell": "8:3-8:11|10963370434658308541|2|5186|-1", + "extent": "8:3-8:26|10963370434658308541|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -51,8 +51,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:11-2:12|11628904180681204356|2|1090", - "extent": "2:3-2:23|11628904180681204356|2|0", + "spell": "2:11-2:17|11628904180681204356|2|1090|-1", + "extent": "2:3-2:23|11628904180681204356|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -66,8 +66,8 @@ OUTPUT: "short_name": "Derived", "kind": 23, "declarations": [], - "spell": "7:8-7:15|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:8-7:15|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "alias_of": 0, "bases": [11628904180681204356, 15826803741381445676], "derived": [], @@ -75,7 +75,7 @@ OUTPUT: "funcs": [13164726294460837993], "vars": [], "instances": [], - "uses": ["8:4-8:11|10963370434658308541|2|4"] + "uses": ["8:4-8:11|10963370434658308541|2|4|-1"] }, { "usr": 11628904180681204356, "detailed_name": "struct Base0 {}", @@ -83,8 +83,8 @@ OUTPUT: "short_name": "Base0", "kind": 23, "declarations": [], - "spell": "1:8-1:13|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:13|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -92,7 +92,7 @@ OUTPUT: "funcs": [16347272523198263017], "vars": [], "instances": [], - "uses": ["2:12-2:17|11628904180681204356|2|4", "7:18-7:23|10963370434658308541|2|2052"] + "uses": ["2:12-2:17|11628904180681204356|2|4|-1", "7:18-7:23|10963370434658308541|2|2052|-1"] }, { "usr": 15826803741381445676, "detailed_name": "struct Base1 {}", @@ -100,8 +100,8 @@ OUTPUT: "short_name": "Base1", "kind": 23, "declarations": [], - "spell": "4:8-4:13|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:8-4:13|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [10963370434658308541], @@ -109,7 +109,7 @@ OUTPUT: "funcs": [8401779086123965305], "vars": [], "instances": [], - "uses": ["5:12-5:17|15826803741381445676|2|4", "7:25-7:30|10963370434658308541|2|2052"] + "uses": ["5:12-5:17|15826803741381445676|2|4|-1", "7:25-7:30|10963370434658308541|2|2052|-1"] }], "usr2var": [] } diff --git a/index_tests/lambdas/lambda.cc b/index_tests/lambdas/lambda.cc index 357d6e32..b4e58a30 100644 --- a/index_tests/lambdas/lambda.cc +++ b/index_tests/lambdas/lambda.cc @@ -24,8 +24,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-12:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-12:2|0|1|0|-1", "bases": [], "derived": [], "vars": [12666114896600231317, 2981279427664991319], @@ -42,7 +42,7 @@ OUTPUT: "bases": [], "derived": [], "vars": [], - "uses": ["9:14-9:15|4259594751088586730|3|16420", "10:14-10:15|4259594751088586730|3|16420", "11:14-11:15|4259594751088586730|3|16420"], + "uses": ["9:14-9:15|4259594751088586730|3|16420|-1", "10:14-10:15|4259594751088586730|3|16420|-1", "11:14-11:15|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -65,10 +65,8 @@ OUTPUT: "detailed_name": "", "qual_name_offset": 0, "short_name": "", - "kind": 26, + "kind": 0, "declarations": [], - "spell": "4:22-4:23|4259594751088586730|3|2", - "extent": "4:22-4:23|4259594751088586730|3|0", "alias_of": 0, "bases": [], "derived": [], @@ -85,10 +83,10 @@ OUTPUT: "short_name": "dosomething", "hover": "(lambda) dosomething", "declarations": [], - "spell": "4:8-4:19|4259594751088586730|3|2", - "extent": "4:3-7:4|4259594751088586730|3|0", + "spell": "4:8-4:19|4259594751088586730|3|2|-1", + "extent": "4:3-7:4|4259594751088586730|3|0|-1", "type": 14635009347499519042, - "uses": ["9:3-9:14|4259594751088586730|3|4", "10:3-10:14|4259594751088586730|3|4", "11:3-11:14|4259594751088586730|3|4"], + "uses": ["9:3-9:14|4259594751088586730|3|4|-1", "10:3-10:14|4259594751088586730|3|4|-1", "11:3-11:14|4259594751088586730|3|4|-1"], "kind": 13, "storage": 0 }, { @@ -97,10 +95,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "x", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["4:24-4:25|4259594751088586730|3|4", "5:7-5:8|4259594751088586730|3|28"], + "uses": ["4:24-4:25|4259594751088586730|3|4|-1", "5:7-5:8|4259594751088586730|3|28|-1"], "kind": 13, "storage": 0 }, { @@ -109,10 +107,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "y", "declarations": [], - "spell": "4:31-4:32|17926497908620168464|3|2", - "extent": "4:27-4:32|4259594751088586730|3|0", + "spell": "4:31-4:32|17926497908620168464|3|2|-1", + "extent": "4:27-4:32|4259594751088586730|3|0|-1", "type": 0, - "uses": ["6:7-6:8|4259594751088586730|3|28"], + "uses": ["6:7-6:8|4259594751088586730|3|28|-1"], "kind": 253, "storage": 0 }] diff --git a/index_tests/macros/complex.cc b/index_tests/macros/complex.cc index a74be500..b88c3eaa 100644 --- a/index_tests/macros/complex.cc +++ b/index_tests/macros/complex.cc @@ -23,9 +23,9 @@ OUTPUT: "short_name": "a", "kind": 12, "storage": 0, - "declarations": ["12:1-12:20|0|1|1"], - "spell": "12:1-12:20|0|1|2", - "extent": "12:1-12:20|0|1|0", + "declarations": ["12:1-12:20|12:1-12:20|0|1|1|-1"], + "spell": "12:1-12:20|0|1|2|-1", + "extent": "12:1-12:20|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -39,12 +39,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "6:5-6:10|0|1|2", - "extent": "6:1-8:2|0|1|0", + "spell": "6:5-6:10|0|1|2|-1", + "extent": "6:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["12:5-12:10|9720930732776154610|3|16420", "12:5-12:10|0|1|64|0"], + "uses": ["12:5-12:10|9720930732776154610|3|16420|-1", "12:5-12:10|0|1|64|0"], "callees": [] }], "usr2type": [{ @@ -70,10 +70,10 @@ OUTPUT: "short_name": "make2", "hover": "const int make2 = 5", "declarations": [], - "spell": "9:11-9:16|0|1|2", - "extent": "9:1-9:20|0|1|0", + "spell": "9:11-9:16|0|1|2|-1", + "extent": "9:1-9:20|0|1|0|-1", "type": 53, - "uses": ["12:14-12:19|9720930732776154610|3|12", "12:14-12:19|0|1|64|0"], + "uses": ["12:14-12:19|9720930732776154610|3|12|-1", "12:14-12:19|0|1|64|0"], "kind": 13, "storage": 0 }, { @@ -83,10 +83,10 @@ OUTPUT: "short_name": "FOO", "hover": "#define FOO(aaa, bbb) \\\n int a();\\\n int a() { return aaa + bbb; }", "declarations": [], - "spell": "1:9-1:12|0|1|2", - "extent": "1:9-3:32|0|1|0", + "spell": "1:9-1:12|0|1|2|-1", + "extent": "1:9-3:32|0|1|0|-1", "type": 0, - "uses": ["12:1-12:4|0|1|64"], + "uses": ["12:1-12:4|0|1|64|-1"], "kind": 255, "storage": 0 }] diff --git a/index_tests/macros/foo.cc b/index_tests/macros/foo.cc index 7b7c8b04..156ab237 100644 --- a/index_tests/macros/foo.cc +++ b/index_tests/macros/foo.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 9, "storage": 0, "declarations": [], - "spell": "5:12-5:15|15041163540773201510|2|1026", - "extent": "5:12-5:15|15041163540773201510|2|0", + "spell": "5:12-5:15|15041163540773201510|2|1026|-1", + "extent": "5:12-5:15|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -50,8 +50,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "4:8-4:11|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:8-4:11|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +59,7 @@ OUTPUT: "funcs": [13788753348312146871], "vars": [], "instances": [], - "uses": ["5:12-5:15|15041163540773201510|2|4", "5:12-5:15|0|1|64|0"] + "uses": ["5:12-5:15|15041163540773201510|2|4|-1", "5:12-5:15|0|1|64|0"] }], "usr2var": [{ "usr": 1569772797058982873, @@ -68,10 +68,10 @@ OUTPUT: "short_name": "A", "hover": "#define A 5", "declarations": [], - "spell": "1:9-1:10|0|1|2", - "extent": "1:9-1:12|0|1|0", + "spell": "1:9-1:10|0|1|2|-1", + "extent": "1:9-1:12|0|1|0|-1", "type": 0, - "uses": ["8:9-8:10|0|1|64"], + "uses": ["8:9-8:10|0|1|64|-1"], "kind": 255, "storage": 0 }, { @@ -81,10 +81,10 @@ OUTPUT: "short_name": "DISALLOW", "hover": "#define DISALLOW(type) type(type&&) = delete;", "declarations": [], - "spell": "2:9-2:17|0|1|2", - "extent": "2:9-2:46|0|1|0", + "spell": "2:9-2:17|0|1|2|-1", + "extent": "2:9-2:46|0|1|0|-1", "type": 0, - "uses": ["5:3-5:11|0|1|64"], + "uses": ["5:3-5:11|0|1|64|-1"], "kind": 255, "storage": 0 }, { @@ -94,8 +94,8 @@ OUTPUT: "short_name": "x", "hover": "int x = A", "declarations": [], - "spell": "8:5-8:6|0|1|2", - "extent": "8:1-1:1|0|1|0", + "spell": "8:5-8:6|0|1|2|-1", + "extent": "8:1-1:1|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/method_declaration.cc b/index_tests/method_declaration.cc index 00edb4de..fae12cdc 100644 --- a/index_tests/method_declaration.cc +++ b/index_tests/method_declaration.cc @@ -18,7 +18,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:8-2:11|15041163540773201510|2|1025"], + "declarations": ["2:8-2:11|2:3-2:13|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/method_definition.cc b/index_tests/method_definition.cc index b79e9ba3..895eac04 100644 --- a/index_tests/method_definition.cc +++ b/index_tests/method_definition.cc @@ -16,9 +16,9 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:8-2:11|15041163540773201510|2|1025"], - "spell": "5:11-5:14|15041163540773201510|2|1026", - "extent": "5:1-5:25|15041163540773201510|2|0", + "declarations": ["2:8-2:11|2:3-2:19|15041163540773201510|2|1025|-1"], + "spell": "5:11-5:14|15041163540773201510|2|1026|-1", + "extent": "5:1-5:25|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -41,7 +41,7 @@ OUTPUT: "funcs": [6446764306530590711], "vars": [], "instances": [], - "uses": ["5:6-5:9|0|1|4"] + "uses": ["5:6-5:9|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/method_inline_declaration.cc b/index_tests/method_inline_declaration.cc index 64ced29b..f2294cd0 100644 --- a/index_tests/method_inline_declaration.cc +++ b/index_tests/method_inline_declaration.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:8-2:11|15041163540773201510|2|1026", - "extent": "2:3-2:16|15041163540773201510|2|0", + "spell": "2:8-2:11|15041163540773201510|2|1026|-1", + "extent": "2:3-2:16|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -30,8 +30,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/multi_file/funky_enum.cc b/index_tests/multi_file/funky_enum.cc index c76b4d47..784f210d 100644 --- a/index_tests/multi_file/funky_enum.cc +++ b/index_tests/multi_file/funky_enum.cc @@ -35,8 +35,8 @@ OUTPUT: funky_enum.h "hover": "A = 0", "comments": "This file cannot be built directory. It is included in an enum definition of\nanother file.", "declarations": [], - "spell": "4:1-4:2|16985894625255407295|2|1026", - "extent": "4:1-4:2|16985894625255407295|2|0", + "spell": "4:1-4:2|16985894625255407295|2|1026|-1", + "extent": "4:1-4:2|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -49,8 +49,8 @@ OUTPUT: funky_enum.h "hover": "C = 2", "comments": "This file cannot be built directory. It is included in an enum definition of\nanother file.", "declarations": [], - "spell": "6:1-6:2|16985894625255407295|2|1026", - "extent": "6:1-6:2|16985894625255407295|2|0", + "spell": "6:1-6:2|16985894625255407295|2|1026|-1", + "extent": "6:1-6:2|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -63,8 +63,8 @@ OUTPUT: funky_enum.h "hover": "B = 1", "comments": "This file cannot be built directory. It is included in an enum definition of\nanother file.", "declarations": [], - "spell": "5:1-5:2|16985894625255407295|2|1026", - "extent": "5:1-5:2|16985894625255407295|2|0", + "spell": "5:1-5:2|16985894625255407295|2|1026|-1", + "extent": "5:1-5:2|16985894625255407295|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -81,13 +81,13 @@ OUTPUT: funky_enum.cc "usr2func": [], "usr2type": [{ "usr": 16985894625255407295, - "detailed_name": "enum Foo {\n}", + "detailed_name": "enum Foo {}", "qual_name_offset": 5, "short_name": "Foo", "kind": 10, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/multi_file/impl.cc b/index_tests/multi_file/impl.cc index cc53dabf..dc754b8c 100644 --- a/index_tests/multi_file/impl.cc +++ b/index_tests/multi_file/impl.cc @@ -17,8 +17,8 @@ OUTPUT: header.h "kind": 12, "storage": 0, "declarations": [], - "spell": "10:6-10:10|0|1|2", - "extent": "10:1-10:15|0|1|0", + "spell": "10:6-10:10|0|1|2|-1", + "extent": "10:1-10:15|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -47,8 +47,8 @@ OUTPUT: header.h "short_name": "Foo2", "kind": 23, "declarations": [], - "spell": "13:8-13:12|0|1|2", - "extent": "13:1-13:15|0|1|0", + "spell": "13:8-13:12|0|1|2|-1", + "extent": "13:1-13:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -64,8 +64,8 @@ OUTPUT: header.h "short_name": "Foo0", "kind": 252, "declarations": [], - "spell": "7:7-7:11|0|1|2", - "extent": "7:1-7:29|0|1|0", + "spell": "7:7-7:11|0|1|2|-1", + "extent": "7:1-7:29|0|1|0|-1", "alias_of": 16750616846959666305, "bases": [], "derived": [], @@ -76,13 +76,13 @@ OUTPUT: header.h "uses": [] }, { "usr": 4481210672785600703, - "detailed_name": "enum Foo3 {\n}", + "detailed_name": "enum Foo3 {}", "qual_name_offset": 5, "short_name": "Foo3", "kind": 10, "declarations": [], - "spell": "15:6-15:10|0|1|2", - "extent": "15:1-15:22|0|1|0", + "spell": "15:6-15:10|0|1|2|-1", + "extent": "15:1-15:22|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -98,8 +98,8 @@ OUTPUT: header.h "short_name": "Base", "kind": 23, "declarations": [], - "spell": "3:8-3:12|0|1|2", - "extent": "3:1-3:15|0|1|0", + "spell": "3:8-3:12|0|1|2|-1", + "extent": "3:1-3:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [16750616846959666305], @@ -107,7 +107,7 @@ OUTPUT: header.h "funcs": [], "vars": [], "instances": [], - "uses": ["5:26-5:30|16750616846959666305|2|2052"] + "uses": ["5:26-5:30|16750616846959666305|2|2052|-1"] }, { "usr": 16750616846959666305, "detailed_name": "struct SameFileDerived : Base {}", @@ -115,8 +115,8 @@ OUTPUT: header.h "short_name": "SameFileDerived", "kind": 23, "declarations": [], - "spell": "5:8-5:23|0|1|2", - "extent": "5:1-5:33|0|1|0", + "spell": "5:8-5:23|0|1|2|-1", + "extent": "5:1-5:33|0|1|0|-1", "alias_of": 0, "bases": [8420119006782424779], "derived": [], @@ -124,7 +124,7 @@ OUTPUT: header.h "funcs": [], "vars": [], "instances": [], - "uses": ["7:14-7:29|0|1|4"] + "uses": ["7:14-7:29|0|1|4|-1"] }], "usr2var": [{ "usr": 2638219001294786365, @@ -132,8 +132,8 @@ OUTPUT: header.h "qual_name_offset": 4, "short_name": "Foo4", "declarations": [], - "spell": "17:5-17:9|0|1|2", - "extent": "17:1-17:9|0|1|0", + "spell": "17:5-17:9|0|1|2|-1", + "extent": "17:1-17:9|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -145,8 +145,8 @@ OUTPUT: header.h "short_name": "A", "hover": "A = 0", "declarations": [], - "spell": "15:13-15:14|4481210672785600703|2|1026", - "extent": "15:13-15:14|4481210672785600703|2|0", + "spell": "15:13-15:14|4481210672785600703|2|1026|-1", + "extent": "15:13-15:14|4481210672785600703|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -158,8 +158,8 @@ OUTPUT: header.h "short_name": "C", "hover": "C = 2", "declarations": [], - "spell": "15:19-15:20|4481210672785600703|2|1026", - "extent": "15:19-15:20|4481210672785600703|2|0", + "spell": "15:19-15:20|4481210672785600703|2|1026|-1", + "extent": "15:19-15:20|4481210672785600703|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -170,8 +170,8 @@ OUTPUT: header.h "qual_name_offset": 11, "short_name": "Foo5", "declarations": [], - "spell": "18:12-18:16|0|1|2", - "extent": "18:1-18:16|0|1|0", + "spell": "18:12-18:16|0|1|2|-1", + "extent": "18:1-18:16|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -183,8 +183,8 @@ OUTPUT: header.h "short_name": "B", "hover": "B = 1", "declarations": [], - "spell": "15:16-15:17|4481210672785600703|2|1026", - "extent": "15:16-15:17|4481210672785600703|2|0", + "spell": "15:16-15:17|4481210672785600703|2|1026|-1", + "extent": "15:16-15:17|4481210672785600703|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -206,8 +206,8 @@ OUTPUT: impl.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:10|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:10|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -215,8 +215,8 @@ OUTPUT: impl.cc "callees": ["4:3-4:7|11650481237659640387|3|16420"] }, { "usr": 11650481237659640387, - "detailed_name": "template<> void Foo1()", - "qual_name_offset": 16, + "detailed_name": "void Foo1()", + "qual_name_offset": 5, "short_name": "Foo1", "kind": 12, "storage": 0, @@ -224,7 +224,7 @@ OUTPUT: impl.cc "bases": [], "derived": [], "vars": [], - "uses": ["4:3-4:7|5817708529036841195|3|16420"], + "uses": ["4:3-4:7|5817708529036841195|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/multi_file/simple_impl.cc b/index_tests/multi_file/simple_impl.cc index df6d723e..75b57e37 100644 --- a/index_tests/multi_file/simple_impl.cc +++ b/index_tests/multi_file/simple_impl.cc @@ -16,7 +16,7 @@ OUTPUT: simple_header.h "short_name": "header", "kind": 12, "storage": 0, - "declarations": ["3:6-3:12|0|1|1"], + "declarations": ["3:6-3:12|3:1-3:14|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -41,8 +41,8 @@ OUTPUT: simple_impl.cc "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:10|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:10|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -59,7 +59,7 @@ OUTPUT: simple_impl.cc "bases": [], "derived": [], "vars": [], - "uses": ["4:3-4:9|3373269392705484958|3|16420"], + "uses": ["4:3-4:9|3373269392705484958|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/multi_file/static.cc b/index_tests/multi_file/static.cc index 7b255c5d..50096fb2 100644 --- a/index_tests/multi_file/static.cc +++ b/index_tests/multi_file/static.cc @@ -14,7 +14,7 @@ OUTPUT: static.h "short_name": "CreateSharedBuffer", "kind": 254, "storage": 0, - "declarations": ["4:15-4:33|9411323049603567600|2|1025"], + "declarations": ["4:15-4:33|4:3-4:35|9411323049603567600|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -28,8 +28,8 @@ OUTPUT: static.h "short_name": "Buffer", "kind": 23, "declarations": [], - "spell": "3:8-3:14|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:8-3:14|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -50,14 +50,14 @@ OUTPUT: static.cc "skipped_ranges": [], "usr2func": [{ "usr": 14576076421851654759, - "detailed_name": "void Buffer::CreateSharedBuffer()", - "qual_name_offset": 5, + "detailed_name": "static void Buffer::CreateSharedBuffer()", + "qual_name_offset": 12, "short_name": "CreateSharedBuffer", "kind": 254, "storage": 0, "declarations": [], - "spell": "3:14-3:32|9411323049603567600|2|1026", - "extent": "3:1-3:37|9411323049603567600|2|0", + "spell": "3:14-3:32|9411323049603567600|2|1026|-1", + "extent": "3:1-3:37|9411323049603567600|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -78,7 +78,7 @@ OUTPUT: static.cc "funcs": [14576076421851654759], "vars": [], "instances": [], - "uses": ["3:6-3:12|0|1|4"] + "uses": ["3:6-3:12|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/namespaces/anonymous_function.cc b/index_tests/namespaces/anonymous_function.cc index eb89d959..89d660a7 100644 --- a/index_tests/namespaces/anonymous_function.cc +++ b/index_tests/namespaces/anonymous_function.cc @@ -14,7 +14,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["2:6-2:9|7144845543074395457|2|1"], + "declarations": ["2:6-2:9|2:1-2:11|7144845543074395457|2|1|-1"], "bases": [], "derived": [], "vars": [], diff --git a/index_tests/namespaces/function_declaration.cc b/index_tests/namespaces/function_declaration.cc index 2438c99c..9ca5a4d8 100644 --- a/index_tests/namespaces/function_declaration.cc +++ b/index_tests/namespaces/function_declaration.cc @@ -14,7 +14,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["2:6-2:9|2029211996748007610|2|1025"], + "declarations": ["2:6-2:9|2:1-2:23|2029211996748007610|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -23,11 +23,11 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-3:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/function_definition.cc b/index_tests/namespaces/function_definition.cc index 7afe9d29..e732b06e 100644 --- a/index_tests/namespaces/function_definition.cc +++ b/index_tests/namespaces/function_definition.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:9|2029211996748007610|2|1026", - "extent": "2:1-2:14|2029211996748007610|2|0", + "spell": "2:6-2:9|2029211996748007610|2|1026|-1", + "extent": "2:1-2:14|2029211996748007610|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -25,11 +25,11 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-3:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/method_declaration.cc b/index_tests/namespaces/method_declaration.cc index 48a8456e..b957b1d5 100644 --- a/index_tests/namespaces/method_declaration.cc +++ b/index_tests/namespaces/method_declaration.cc @@ -16,7 +16,7 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["3:8-3:11|4508214972876735896|2|1025"], + "declarations": ["3:8-3:11|3:3-3:13|4508214972876735896|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -25,11 +25,11 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-5:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -45,8 +45,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|2029211996748007610|2|1026", - "extent": "2:1-4:2|2029211996748007610|2|0", + "spell": "2:7-2:10|2029211996748007610|2|1026|-1", + "extent": "2:1-4:2|2029211996748007610|2|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/method_definition.cc b/index_tests/namespaces/method_definition.cc index 2506e411..00f55200 100644 --- a/index_tests/namespaces/method_definition.cc +++ b/index_tests/namespaces/method_definition.cc @@ -18,9 +18,9 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["3:8-3:11|4508214972876735896|2|1025"], - "spell": "6:11-6:14|4508214972876735896|2|1026", - "extent": "6:1-6:19|4508214972876735896|2|0", + "declarations": ["3:8-3:11|3:3-3:13|4508214972876735896|2|1025|-1"], + "spell": "6:11-6:14|4508214972876735896|2|1026|-1", + "extent": "6:1-6:19|4508214972876735896|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -29,11 +29,11 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -49,8 +49,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|2029211996748007610|2|1026", - "extent": "2:1-4:2|2029211996748007610|2|0", + "spell": "2:7-2:10|2029211996748007610|2|1026|-1", + "extent": "2:1-4:2|2029211996748007610|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -58,7 +58,7 @@ OUTPUT: "funcs": [10487325150128053272], "vars": [], "instances": [], - "uses": ["6:6-6:9|2029211996748007610|2|4"] + "uses": ["6:6-6:9|2029211996748007610|2|4|-1"] }], "usr2var": [] } diff --git a/index_tests/namespaces/method_inline_declaration.cc b/index_tests/namespaces/method_inline_declaration.cc index 55c95118..4d048be1 100644 --- a/index_tests/namespaces/method_inline_declaration.cc +++ b/index_tests/namespaces/method_inline_declaration.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "3:8-3:11|4508214972876735896|2|1026", - "extent": "3:3-3:16|4508214972876735896|2|0", + "spell": "3:8-3:11|4508214972876735896|2|1026|-1", + "extent": "3:3-3:16|4508214972876735896|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -27,11 +27,11 @@ OUTPUT: }], "usr2type": [{ "usr": 2029211996748007610, - "detailed_name": "namespace hello {\n}", + "detailed_name": "namespace hello {}", "qual_name_offset": 10, "short_name": "hello", "kind": 3, - "declarations": ["1:11-1:16|0|1|1"], + "declarations": ["1:11-1:16|1:1-5:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -47,8 +47,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|2029211996748007610|2|1026", - "extent": "2:1-4:2|2029211996748007610|2|0", + "spell": "2:7-2:10|2029211996748007610|2|1026|-1", + "extent": "2:1-4:2|2029211996748007610|2|0|-1", "alias_of": 0, "bases": [], "derived": [], diff --git a/index_tests/namespaces/namespace_alias.cc b/index_tests/namespaces/namespace_alias.cc index b659f553..b8cbce9c 100644 --- a/index_tests/namespaces/namespace_alias.cc +++ b/index_tests/namespaces/namespace_alias.cc @@ -26,8 +26,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "11:6-11:10|0|1|2", - "extent": "11:1-14:2|0|1|0", + "spell": "11:6-11:10|0|1|2|-1", + "extent": "11:1-14:2|0|1|0|-1", "bases": [], "derived": [], "vars": [6030927277961448585, 7657277353101371136], @@ -51,11 +51,11 @@ OUTPUT: "uses": [] }, { "usr": 926793467007732869, - "detailed_name": "namespace foo {\n}", + "detailed_name": "namespace foo {}", "qual_name_offset": 10, "short_name": "foo", "kind": 3, - "declarations": ["1:11-1:14|0|1|1"], + "declarations": ["1:11-1:14|1:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [17805385787823406700], @@ -63,14 +63,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:17-9:20|0|1|4", "12:11-12:14|10818727483146447186|3|4"] + "uses": ["9:17-9:20|0|1|4|-1", "12:11-12:14|10818727483146447186|3|4|-1"] }, { "usr": 11879713791858506216, "detailed_name": "namespace fbz = foo::bar::baz", "qual_name_offset": 10, "short_name": "fbz", "kind": 252, - "declarations": ["9:11-9:14|0|1|1"], + "declarations": ["9:11-9:14|9:1-9:30|0|1|1|-1"], "alias_of": 14450849931009540802, "bases": [], "derived": [], @@ -78,14 +78,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["13:11-13:14|10818727483146447186|3|4"] + "uses": ["13:11-13:14|10818727483146447186|3|4|-1"] }, { "usr": 14450849931009540802, - "detailed_name": "namespace foo::bar::baz {\n}", + "detailed_name": "namespace foo::bar::baz {}", "qual_name_offset": 10, "short_name": "baz", "kind": 3, - "declarations": ["3:20-3:23|17805385787823406700|2|1025"], + "declarations": ["3:20-3:23|3:10-5:11|17805385787823406700|2|1025|-1"], "alias_of": 0, "bases": [17805385787823406700], "derived": [], @@ -96,14 +96,14 @@ OUTPUT: "R": -1 }], "instances": [], - "uses": ["9:27-9:30|0|1|4", "12:21-12:24|10818727483146447186|3|4"] + "uses": ["9:27-9:30|0|1|4|-1", "12:21-12:24|10818727483146447186|3|4|-1"] }, { "usr": 17805385787823406700, - "detailed_name": "namespace foo::bar {\n}", + "detailed_name": "namespace foo::bar {}", "qual_name_offset": 10, "short_name": "bar", "kind": 3, - "declarations": ["2:15-2:18|926793467007732869|2|1025"], + "declarations": ["2:15-2:18|2:5-6:6|926793467007732869|2|1025|-1"], "alias_of": 0, "bases": [926793467007732869], "derived": [14450849931009540802], @@ -111,7 +111,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:22-9:25|0|1|4", "12:16-12:19|10818727483146447186|3|4"] + "uses": ["9:22-9:25|0|1|4|-1", "12:16-12:19|10818727483146447186|3|4|-1"] }], "usr2var": [{ "usr": 6030927277961448585, @@ -120,8 +120,8 @@ OUTPUT: "short_name": "a", "hover": "int a = foo::bar::baz::qux", "declarations": [], - "spell": "12:7-12:8|10818727483146447186|3|2", - "extent": "12:3-12:29|10818727483146447186|3|0", + "spell": "12:7-12:8|10818727483146447186|3|2|-1", + "extent": "12:3-12:29|10818727483146447186|3|0|-1", "type": 53, "uses": [], "kind": 13, @@ -133,8 +133,8 @@ OUTPUT: "short_name": "b", "hover": "int b = fbz::qux", "declarations": [], - "spell": "13:7-13:8|10818727483146447186|3|2", - "extent": "13:3-13:19|10818727483146447186|3|0", + "spell": "13:7-13:8|10818727483146447186|3|2|-1", + "extent": "13:3-13:19|10818727483146447186|3|0|-1", "type": 53, "uses": [], "kind": 13, @@ -146,10 +146,10 @@ OUTPUT: "short_name": "qux", "hover": "int foo::bar::baz::qux = 42", "declarations": [], - "spell": "4:18-4:21|14450849931009540802|2|1026", - "extent": "4:14-4:26|14450849931009540802|2|0", + "spell": "4:18-4:21|14450849931009540802|2|1026|-1", + "extent": "4:14-4:26|14450849931009540802|2|0|-1", "type": 53, - "uses": ["12:26-12:29|10818727483146447186|3|12", "13:16-13:19|10818727483146447186|3|12"], + "uses": ["12:26-12:29|10818727483146447186|3|12|-1", "13:16-13:19|10818727483146447186|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/namespaces/namespace_reference.cc b/index_tests/namespaces/namespace_reference.cc index 16949403..4565040d 100644 --- a/index_tests/namespaces/namespace_reference.cc +++ b/index_tests/namespaces/namespace_reference.cc @@ -22,8 +22,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "6:6-6:12|0|1|2", - "extent": "6:1-10:2|0|1|0", + "spell": "6:6-6:12|0|1|2|-1", + "extent": "6:1-10:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -37,12 +37,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:8-3:14|11072669167287398027|2|1026", - "extent": "3:3-3:24|11072669167287398027|2|0", + "spell": "3:8-3:14|11072669167287398027|2|1026|-1", + "extent": "3:3-3:24|11072669167287398027|2|0|-1", "bases": [], "derived": [], "vars": [3649375698083002347], - "uses": ["7:7-7:13|631910859630953711|3|16420", "9:3-9:9|631910859630953711|3|16420"], + "uses": ["7:7-7:13|631910859630953711|3|16420|-1", "9:3-9:9|631910859630953711|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -62,11 +62,11 @@ OUTPUT: "uses": [] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-4:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -77,7 +77,7 @@ OUTPUT: "R": -1 }], "instances": [], - "uses": ["7:3-7:5|631910859630953711|3|4", "7:14-7:16|631910859630953711|3|4", "8:19-8:21|631910859630953711|3|4"] + "uses": ["7:3-7:5|631910859630953711|3|4|-1", "7:14-7:16|631910859630953711|3|4|-1", "8:19-8:21|631910859630953711|3|4|-1"] }], "usr2var": [{ "usr": 3649375698083002347, @@ -85,8 +85,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "3:19-3:20|17328473273923617489|3|1026", - "extent": "3:15-3:20|17328473273923617489|3|0", + "spell": "3:19-3:20|17328473273923617489|3|1026|-1", + "extent": "3:15-3:20|17328473273923617489|3|0|-1", "type": 53, "uses": [], "kind": 253, @@ -97,10 +97,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "Foo", "declarations": [], - "spell": "2:7-2:10|11072669167287398027|2|1026", - "extent": "2:3-2:10|11072669167287398027|2|0", + "spell": "2:7-2:10|11072669167287398027|2|1026|-1", + "extent": "2:3-2:10|11072669167287398027|2|0|-1", "type": 53, - "uses": ["7:18-7:21|631910859630953711|3|12", "9:10-9:13|631910859630953711|3|12"], + "uses": ["7:18-7:21|631910859630953711|3|12|-1", "9:10-9:13|631910859630953711|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/operators/operator.cc b/index_tests/operators/operator.cc index e05be650..009db1c0 100644 --- a/index_tests/operators/operator.cc +++ b/index_tests/operators/operator.cc @@ -18,7 +18,7 @@ OUTPUT: "short_name": "operator()", "kind": 6, "storage": 0, - "declarations": ["3:8-3:16|15041163540773201510|2|1025"], + "declarations": ["3:8-3:16|3:3-3:24|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -31,7 +31,7 @@ OUTPUT: "short_name": "operator()", "kind": 6, "storage": 0, - "declarations": ["4:7-4:15|15041163540773201510|2|1025"], + "declarations": ["4:7-4:15|4:3-4:31|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -45,8 +45,8 @@ OUTPUT: "kind": 6, "storage": 0, "declarations": [], - "spell": "2:8-2:16|15041163540773201510|2|1026", - "extent": "2:3-2:27|15041163540773201510|2|0", + "spell": "2:8-2:18|15041163540773201510|2|1026|-1", + "extent": "2:3-2:27|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -59,7 +59,7 @@ OUTPUT: "short_name": "operator+=", "kind": 12, "storage": 0, - "declarations": ["7:6-7:14|0|1|1"], + "declarations": ["7:6-7:14|7:1-7:42|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -73,8 +73,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -82,7 +82,7 @@ OUTPUT: "funcs": [7874436189163837815, 3545323327609582678, 3986818119971932909], "vars": [], "instances": [], - "uses": ["7:1-7:4|0|1|4", "7:25-7:28|0|1|4"] + "uses": ["7:1-7:4|0|1|4|-1", "7:25-7:28|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/outline/static_function_in_type.cc b/index_tests/outline/static_function_in_type.cc index 89842296..c29aae07 100644 --- a/index_tests/outline/static_function_in_type.cc +++ b/index_tests/outline/static_function_in_type.cc @@ -18,7 +18,7 @@ OUTPUT: static_function_in_type.h "short_name": "Register", "kind": 254, "storage": 0, - "declarations": ["6:15-6:23|17262466801709381811|2|1025"], + "declarations": ["6:15-6:23|6:3-6:33|17262466801709381811|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -31,7 +31,7 @@ OUTPUT: static_function_in_type.h "qual_name_offset": 6, "short_name": "Manager", "kind": 5, - "declarations": ["3:7-3:14|11072669167287398027|2|1025"], + "declarations": ["3:7-3:14|3:1-3:14|11072669167287398027|2|1025|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -39,14 +39,14 @@ OUTPUT: static_function_in_type.h "funcs": [], "vars": [], "instances": [], - "uses": ["6:24-6:31|17262466801709381811|2|4"] + "uses": ["6:24-6:31|17262466801709381811|2|4|-1"] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-9:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -62,8 +62,8 @@ OUTPUT: static_function_in_type.h "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|11072669167287398027|2|1026", - "extent": "5:1-7:2|11072669167287398027|2|0", + "spell": "5:8-5:11|11072669167287398027|2|1026|-1", + "extent": "5:1-7:2|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -84,15 +84,15 @@ OUTPUT: static_function_in_type.cc "skipped_ranges": [], "usr2func": [{ "usr": 17019747379608639279, - "detailed_name": "void Foo::Register(ns::Manager *m)", - "qual_name_offset": 5, + "detailed_name": "static void ns::Foo::Register(ns::Manager *)", + "qual_name_offset": 12, "short_name": "Register", "kind": 254, "storage": 0, "comments": "static", "declarations": [], - "spell": "5:11-5:19|17262466801709381811|2|1026", - "extent": "5:1-6:2|17262466801709381811|2|0", + "spell": "5:11-5:19|17262466801709381811|2|1026|-1", + "extent": "5:1-6:2|17262466801709381811|2|0|-1", "bases": [], "derived": [], "vars": [13569879755236306838], @@ -113,14 +113,14 @@ OUTPUT: static_function_in_type.cc "funcs": [], "vars": [], "instances": [13569879755236306838], - "uses": ["5:20-5:27|11072669167287398027|2|4"] + "uses": ["5:20-5:27|11072669167287398027|2|4|-1"] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["3:11-3:13|0|1|1"], + "declarations": ["3:11-3:13|3:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -143,7 +143,7 @@ OUTPUT: static_function_in_type.cc "funcs": [17019747379608639279], "vars": [], "instances": [], - "uses": ["5:6-5:9|11072669167287398027|2|4"] + "uses": ["5:6-5:9|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 13569879755236306838, @@ -151,8 +151,8 @@ OUTPUT: static_function_in_type.cc "qual_name_offset": 13, "short_name": "m", "declarations": [], - "spell": "5:29-5:30|17019747379608639279|3|1026", - "extent": "5:20-5:30|17019747379608639279|3|0", + "spell": "5:29-5:30|17019747379608639279|3|1026|-1", + "extent": "5:20-5:30|17019747379608639279|3|0|-1", "type": 1972401196751872203, "uses": [], "kind": 253, diff --git a/index_tests/preprocessor/include_guard.cc b/index_tests/preprocessor/include_guard.cc index 5b4ef807..d9d069f7 100644 --- a/index_tests/preprocessor/include_guard.cc +++ b/index_tests/preprocessor/include_guard.cc @@ -17,8 +17,8 @@ OUTPUT: "short_name": "FOO", "hover": "#define FOO", "declarations": [], - "spell": "2:9-2:12|0|1|2", - "extent": "2:9-2:12|0|1|0", + "spell": "2:9-2:12|0|1|2|-1", + "extent": "2:9-2:12|0|1|0|-1", "type": 0, "uses": [], "kind": 255, diff --git a/index_tests/templates/func_specialized_template_param.cc b/index_tests/templates/func_specialized_template_param.cc index 7d5f44be..af88d365 100644 --- a/index_tests/templates/func_specialized_template_param.cc +++ b/index_tests/templates/func_specialized_template_param.cc @@ -19,9 +19,9 @@ OUTPUT: "short_name": "Bar", "kind": 6, "storage": 0, - "declarations": ["5:8-5:11|15041163540773201510|2|1025"], - "spell": "8:11-8:14|15041163540773201510|2|1026", - "extent": "8:1-8:36|15041163540773201510|2|0", + "declarations": ["5:8-5:11|5:3-5:30|15041163540773201510|2|1025|-1"], + "spell": "8:11-8:14|15041163540773201510|2|1026|-1", + "extent": "8:1-8:36|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -29,29 +29,14 @@ OUTPUT: "callees": [] }], "usr2type": [{ - "usr": 2100211316767379401, - "detailed_name": "template<> class Template", - "qual_name_offset": 17, - "short_name": "Template", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["5:12-5:20|15041163540773201510|2|4", "8:15-8:23|0|1|4"] - }, { "usr": 15041163540773201510, "detailed_name": "struct Foo {}", "qual_name_offset": 7, "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "4:8-4:11|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:8-4:11|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +44,7 @@ OUTPUT: "funcs": [8412238651648388423], "vars": [], "instances": [], - "uses": ["8:6-8:9|0|1|4"] + "uses": ["8:6-8:9|0|1|4|-1"] }, { "usr": 17107291254533526269, "detailed_name": "class Template {}", @@ -67,8 +52,8 @@ OUTPUT: "short_name": "Template", "kind": 5, "declarations": [], - "spell": "2:7-2:15|0|1|2", - "extent": "2:1-2:18|0|1|0", + "spell": "2:7-2:15|0|1|2|-1", + "extent": "2:1-2:18|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -76,7 +61,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": [] + "uses": ["5:12-5:20|15041163540773201510|2|4|-1", "8:15-8:23|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/templates/implicit_variable_instantiation.cc b/index_tests/templates/implicit_variable_instantiation.cc index db370e9f..6548d39b 100644 --- a/index_tests/templates/implicit_variable_instantiation.cc +++ b/index_tests/templates/implicit_variable_instantiation.cc @@ -37,13 +37,13 @@ OUTPUT: "uses": [] }, { "usr": 1532099849728741556, - "detailed_name": "enum ns::VarType {\n}", + "detailed_name": "enum ns::VarType {}", "qual_name_offset": 5, "short_name": "VarType", "kind": 10, "declarations": [], - "spell": "2:8-2:15|11072669167287398027|2|1026", - "extent": "2:3-2:18|11072669167287398027|2|0", + "spell": "2:8-2:15|11072669167287398027|2|1026|-1", + "extent": "2:3-2:18|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -51,14 +51,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [4731849186641714451, 4731849186641714451], - "uses": ["6:22-6:29|12688716854043726585|2|4", "6:44-6:51|12688716854043726585|2|4", "10:18-10:25|11072669167287398027|2|4"] + "uses": ["6:22-6:29|12688716854043726585|2|4|-1", "6:44-6:51|12688716854043726585|2|4|-1", "10:18-10:25|11072669167287398027|2|4|-1"] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-15:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -80,8 +80,8 @@ OUTPUT: "short_name": "Holder", "kind": 23, "declarations": [], - "spell": "5:10-5:16|11072669167287398027|2|1026", - "extent": "5:3-7:4|11072669167287398027|2|0", + "spell": "5:10-5:16|11072669167287398027|2|1026|-1", + "extent": "5:3-7:4|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -89,7 +89,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:26-10:32|11072669167287398027|2|4", "13:13-13:19|11072669167287398027|2|4", "14:14-14:20|11072669167287398027|2|4"] + "uses": ["10:26-10:32|11072669167287398027|2|4|-1", "13:13-13:19|11072669167287398027|2|4|-1", "14:14-14:20|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 4731849186641714451, @@ -97,11 +97,11 @@ OUTPUT: "qual_name_offset": 29, "short_name": "static_var", "hover": "static constexpr ns::VarType ns::Holder::static_var = (VarType)0x0", - "declarations": ["6:30-6:40|12688716854043726585|2|1025"], - "spell": "10:37-10:47|12688716854043726585|2|1026", - "extent": "9:3-10:47|12688716854043726585|2|0", + "declarations": ["6:30-6:40|6:5-6:55|12688716854043726585|2|1025|-1"], + "spell": "10:37-10:47|12688716854043726585|2|1026|-1", + "extent": "9:3-10:47|12688716854043726585|2|0|-1", "type": 1532099849728741556, - "uses": ["13:26-13:36|11072669167287398027|2|12", "14:27-14:37|11072669167287398027|2|12"], + "uses": ["13:26-13:36|11072669167287398027|2|12|-1", "14:27-14:37|11072669167287398027|2|12|-1"], "kind": 13, "storage": 2 }, { @@ -111,8 +111,8 @@ OUTPUT: "short_name": "Foo2", "hover": "int ns::Foo2 = Holder::static_var", "declarations": [], - "spell": "14:7-14:11|11072669167287398027|2|1026", - "extent": "14:3-14:37|11072669167287398027|2|0", + "spell": "14:7-14:11|11072669167287398027|2|1026|-1", + "extent": "14:3-14:37|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, @@ -124,8 +124,8 @@ OUTPUT: "short_name": "Foo", "hover": "int ns::Foo = Holder::static_var", "declarations": [], - "spell": "13:7-13:10|11072669167287398027|2|1026", - "extent": "13:3-13:36|11072669167287398027|2|0", + "spell": "13:7-13:10|11072669167287398027|2|1026|-1", + "extent": "13:3-13:36|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/member_ref_in_template.cc b/index_tests/templates/member_ref_in_template.cc index e4b59391..312441e2 100644 --- a/index_tests/templates/member_ref_in_template.cc +++ b/index_tests/templates/member_ref_in_template.cc @@ -33,8 +33,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:9|0|1|2", - "extent": "8:1-8:11|0|1|0", + "spell": "8:6-8:9|0|1|2|-1", + "extent": "8:1-8:11|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -47,7 +47,7 @@ OUTPUT: "short_name": "bar", "kind": 6, "storage": 0, - "declarations": ["4:8-4:11|8402783583255987702|2|1025"], + "declarations": ["4:8-4:11|4:3-4:13|8402783583255987702|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -61,8 +61,8 @@ OUTPUT: "short_name": "C", "kind": 23, "declarations": [], - "spell": "2:8-2:9|0|1|2", - "extent": "2:1-5:2|0|1|0", + "spell": "2:8-2:9|0|1|2|-1", + "extent": "2:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -81,8 +81,8 @@ OUTPUT: "short_name": "T", "kind": 26, "declarations": [], - "spell": "1:17-1:18|8402783583255987702|2|2", - "extent": "1:11-1:18|8402783583255987702|2|0", + "spell": "1:17-1:18|8402783583255987702|2|2|-1", + "extent": "1:11-1:18|8402783583255987702|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -98,8 +98,8 @@ OUTPUT: "qual_name_offset": 2, "short_name": "x", "declarations": [], - "spell": "3:5-3:6|8402783583255987702|2|1026", - "extent": "3:3-3:6|8402783583255987702|2|0", + "spell": "3:5-3:6|8402783583255987702|2|1026|-1", + "extent": "3:3-3:6|8402783583255987702|2|0|-1", "type": 14750650276757822712, "uses": [], "kind": 8, diff --git a/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc b/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc index 073ba344..a9005f18 100644 --- a/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc +++ b/index_tests/templates/namespace_template_class_template_func_usage_folded_into_one.cc @@ -24,12 +24,12 @@ OUTPUT: "kind": 254, "storage": 0, "declarations": [], - "spell": "5:16-5:19|14042997404480181958|2|1026", - "extent": "5:5-7:6|14042997404480181958|2|0", + "spell": "5:16-5:19|14042997404480181958|2|1026|-1", + "extent": "5:5-7:6|14042997404480181958|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["10:21-10:24|11072669167287398027|2|36", "11:22-11:25|11072669167287398027|2|36"], + "uses": ["10:21-10:24|11072669167287398027|2|36|-1", "11:22-11:25|11072669167287398027|2|36|-1"], "callees": [] }], "usr2type": [{ @@ -49,11 +49,11 @@ OUTPUT: "uses": [] }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-12:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -75,8 +75,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "3:10-3:13|11072669167287398027|2|1026", - "extent": "3:3-8:4|11072669167287398027|2|0", + "spell": "3:10-3:13|11072669167287398027|2|1026|-1", + "extent": "3:3-8:4|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -84,7 +84,7 @@ OUTPUT: "funcs": [8221803074608342407], "vars": [], "instances": [], - "uses": ["10:11-10:14|11072669167287398027|2|4", "11:11-11:14|11072669167287398027|2|4"] + "uses": ["10:11-10:14|11072669167287398027|2|4|-1", "11:11-11:14|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 3182917058194750998, @@ -93,8 +93,8 @@ OUTPUT: "short_name": "b", "hover": "int ns::b = Foo::foo()", "declarations": [], - "spell": "11:7-11:8|11072669167287398027|2|1026", - "extent": "11:3-11:35|11072669167287398027|2|0", + "spell": "11:7-11:8|11072669167287398027|2|1026|-1", + "extent": "11:3-11:35|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, @@ -106,8 +106,8 @@ OUTPUT: "short_name": "a", "hover": "int ns::a = Foo::foo()", "declarations": [], - "spell": "10:7-10:8|11072669167287398027|2|1026", - "extent": "10:3-10:33|11072669167287398027|2|0", + "spell": "10:7-10:8|11072669167287398027|2|1026|-1", + "extent": "10:3-10:33|11072669167287398027|2|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc index 5b141b39..b3144b08 100644 --- a/index_tests/templates/namespace_template_type_usage_folded_into_one.cc +++ b/index_tests/templates/namespace_template_type_usage_folded_into_one.cc @@ -13,46 +13,12 @@ OUTPUT: "skipped_ranges": [], "usr2func": [], "usr2type": [{ - "usr": 3948666349864691553, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|2", - "extent": "2:3-3:15|11072669167287398027|2|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [3182917058194750998], - "uses": [] - }, { - "usr": 8224244241460152567, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|2", - "extent": "2:3-3:15|11072669167287398027|2|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [15768138241775955040], - "uses": [] - }, { "usr": 11072669167287398027, - "detailed_name": "namespace ns {\n}", + "detailed_name": "namespace ns {}", "qual_name_offset": 10, "short_name": "ns", "kind": 3, - "declarations": ["1:11-1:13|0|1|1"], + "declarations": ["1:11-1:13|1:1-7:2|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -74,16 +40,16 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "3:9-3:12|11072669167287398027|2|1026", - "extent": "3:3-3:15|11072669167287398027|2|0", + "spell": "3:9-3:12|11072669167287398027|2|1026|-1", + "extent": "3:3-3:15|11072669167287398027|2|0|-1", "alias_of": 0, "bases": [], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["5:3-5:6|11072669167287398027|2|4", "6:3-6:6|11072669167287398027|2|4"] + "instances": [15768138241775955040, 3182917058194750998], + "uses": ["5:3-5:6|11072669167287398027|2|4|-1", "6:3-6:6|11072669167287398027|2|4|-1"] }], "usr2var": [{ "usr": 3182917058194750998, @@ -91,9 +57,9 @@ OUTPUT: "qual_name_offset": 10, "short_name": "b", "declarations": [], - "spell": "6:13-6:14|11072669167287398027|2|1026", - "extent": "6:3-6:14|11072669167287398027|2|0", - "type": 3948666349864691553, + "spell": "6:13-6:14|11072669167287398027|2|1026|-1", + "extent": "6:3-6:14|11072669167287398027|2|0|-1", + "type": 14042997404480181958, "uses": [], "kind": 13, "storage": 0 @@ -103,9 +69,9 @@ OUTPUT: "qual_name_offset": 9, "short_name": "a", "declarations": [], - "spell": "5:12-5:13|11072669167287398027|2|1026", - "extent": "5:3-5:13|11072669167287398027|2|0", - "type": 8224244241460152567, + "spell": "5:12-5:13|11072669167287398027|2|1026|-1", + "extent": "5:3-5:13|11072669167287398027|2|0|-1", + "type": 14042997404480181958, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/templates/specialization.cc b/index_tests/templates/specialization.cc index f5ca0f26..52cfe543 100644 --- a/index_tests/templates/specialization.cc +++ b/index_tests/templates/specialization.cc @@ -54,7 +54,7 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["43:6-43:9|0|1|1"], + "declarations": ["43:6-43:9|42:1-43:50|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -67,7 +67,7 @@ OUTPUT: "short_name": "clear", "kind": 6, "storage": 0, - "declarations": ["27:8-27:13|1663022413889915338|2|1025"], + "declarations": ["27:8-27:13|27:3-27:15|1663022413889915338|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -81,8 +81,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "39:6-39:9|0|1|2", - "extent": "39:1-39:21|0|1|0", + "spell": "39:6-39:9|0|1|2|-1", + "extent": "39:1-39:21|0|1|0|-1", "bases": [], "derived": [], "vars": [17826688417349629938], @@ -95,7 +95,7 @@ OUTPUT: "short_name": "clear", "kind": 6, "storage": 0, - "declarations": ["13:8-13:13|7440942986741176606|2|1025"], + "declarations": ["13:8-13:13|13:3-13:15|7440942986741176606|2|1025|-1"], "bases": [], "derived": [], "vars": [], @@ -124,16 +124,16 @@ OUTPUT: "short_name": "function", "kind": 5, "declarations": [], - "spell": "5:7-5:15|0|1|2", - "extent": "4:1-5:30|0|1|0", + "spell": "5:7-5:15|0|1|2|-1", + "extent": "4:1-5:30|0|1|0|-1", "alias_of": 0, "bases": [15019211479263750068], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["7:1-7:9|0|1|4"] + "instances": [2933643612409209903], + "uses": ["7:1-7:9|0|1|4|-1"] }, { "usr": 1663022413889915338, "detailed_name": "template<> class vector> {}", @@ -141,8 +141,8 @@ OUTPUT: "short_name": "vector", "kind": 5, "declarations": [], - "spell": "26:7-26:13|0|1|2", - "extent": "25:1-28:2|0|1|0", + "spell": "26:7-26:13|0|1|2|-1", + "extent": "25:1-28:2|0|1|0|-1", "alias_of": 0, "bases": [7440942986741176606], "derived": [], @@ -150,24 +150,7 @@ OUTPUT: "funcs": [6113470698424012876], "vars": [], "instances": [15931696253641284761], - "uses": ["26:7-26:13|0|1|4", "33:1-33:7|0|1|4"] - }, { - "usr": 3231449734830406187, - "detailed_name": "function", - "qual_name_offset": 0, - "short_name": "function", - "kind": 26, - "declarations": [], - "spell": "5:7-5:15|0|1|2", - "extent": "4:1-5:30|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [2933643612409209903], - "uses": [] + "uses": ["26:7-26:13|0|1|4|-1", "33:1-33:7|0|1|4|-1"] }, { "usr": 5760043510674081814, "detailed_name": "struct Z1 {}", @@ -175,8 +158,8 @@ OUTPUT: "short_name": "Z1", "kind": 23, "declarations": [], - "spell": "19:8-19:10|0|1|2", - "extent": "19:1-19:13|0|1|0", + "spell": "19:8-19:10|0|1|2|-1", + "extent": "19:1-19:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -184,7 +167,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["21:23-21:25|0|1|4", "32:8-32:10|0|1|4"] + "uses": ["21:23-21:25|0|1|4|-1", "32:8-32:10|0|1|4|-1"] }, { "usr": 7440942986741176606, "detailed_name": "class vector {}", @@ -192,25 +175,25 @@ OUTPUT: "short_name": "vector", "kind": 5, "declarations": [], - "spell": "12:7-12:13|0|1|2", - "extent": "12:1-14:2|0|1|0", + "spell": "12:7-12:13|0|1|2|-1", + "extent": "12:1-14:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [16155717907537731864, 1663022413889915338], "types": [], "funcs": [18107614608385228556], "vars": [], - "instances": [], - "uses": ["21:16-21:22|0|1|4", "30:1-30:7|0|1|4", "32:1-32:7|0|1|4"] + "instances": [5792869548777559988], + "uses": ["21:16-21:22|0|1|4|-1", "30:1-30:7|0|1|4|-1", "32:1-32:7|0|1|4|-1"] }, { "usr": 9201299975592934124, - "detailed_name": "enum Enum {\n}", + "detailed_name": "enum Enum {}", "qual_name_offset": 5, "short_name": "Enum", "kind": 10, "declarations": [], - "spell": "35:6-35:10|0|1|2", - "extent": "35:1-37:2|0|1|0", + "spell": "35:6-35:10|0|1|2|-1", + "extent": "35:1-37:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -226,8 +209,8 @@ OUTPUT: "short_name": "Z2", "kind": 23, "declarations": [], - "spell": "23:8-23:10|0|1|2", - "extent": "23:1-23:13|0|1|0", + "spell": "23:8-23:10|0|1|2|-1", + "extent": "23:1-23:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -235,41 +218,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["26:14-26:16|0|1|4", "33:8-33:10|0|1|4"] - }, { - "usr": 11153492883079050853, - "detailed_name": "vector", - "qual_name_offset": 0, - "short_name": "vector", - "kind": 26, - "declarations": [], - "spell": "17:7-17:13|0|1|2", - "extent": "16:1-17:20|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [86949563628772958], - "uses": [] - }, { - "usr": 13322943937025195708, - "detailed_name": "vector", - "qual_name_offset": 0, - "short_name": "vector", - "kind": 26, - "declarations": [], - "spell": "12:7-12:13|0|1|2", - "extent": "11:1-14:2|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [5792869548777559988], - "uses": [] + "uses": ["26:14-26:16|0|1|4|-1", "33:8-33:10|0|1|4|-1"] }, { "usr": 14111105212951082474, "detailed_name": "T", @@ -277,8 +226,8 @@ OUTPUT: "short_name": "T", "kind": 26, "declarations": [], - "spell": "38:20-38:21|17498190318698490707|3|2", - "extent": "38:11-38:21|17498190318698490707|3|0", + "spell": "38:20-38:21|17498190318698490707|3|2|-1", + "extent": "38:11-38:21|17498190318698490707|3|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -293,7 +242,7 @@ OUTPUT: "qual_name_offset": 6, "short_name": "function", "kind": 5, - "declarations": ["2:7-2:15|0|1|1"], + "declarations": ["2:7-2:15|2:1-2:15|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [218068462278884837], @@ -304,13 +253,11 @@ OUTPUT: "uses": [] }, { "usr": 15440970074034693939, - "detailed_name": "vector", + "detailed_name": "", "qual_name_offset": 0, - "short_name": "vector", - "kind": 26, + "short_name": "", + "kind": 0, "declarations": [], - "spell": "21:16-21:22|0|1|2", - "extent": "21:1-21:26|0|1|0", "alias_of": 0, "bases": [], "derived": [], @@ -325,7 +272,7 @@ OUTPUT: "qual_name_offset": 6, "short_name": "allocator", "kind": 5, - "declarations": ["9:28-9:37|0|1|1"], + "declarations": ["9:28-9:37|9:22-9:37|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -341,16 +288,16 @@ OUTPUT: "short_name": "vector", "kind": 5, "declarations": [], - "spell": "17:7-17:13|0|1|2", - "extent": "16:1-17:20|0|1|0", + "spell": "17:7-17:13|0|1|2|-1", + "extent": "16:1-17:20|0|1|0|-1", "alias_of": 0, "bases": [7440942986741176606], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["31:1-31:7|0|1|4"] + "instances": [86949563628772958], + "uses": ["31:1-31:7|0|1|4|-1"] }], "usr2var": [{ "usr": 86949563628772958, @@ -358,9 +305,9 @@ OUTPUT: "qual_name_offset": 14, "short_name": "vip", "declarations": [], - "spell": "31:14-31:17|0|1|2", - "extent": "31:1-31:17|0|1|0", - "type": 11153492883079050853, + "spell": "31:14-31:17|0|1|2|-1", + "extent": "31:1-31:17|0|1|0|-1", + "type": 16155717907537731864, "uses": [], "kind": 13, "storage": 0 @@ -370,9 +317,9 @@ OUTPUT: "qual_name_offset": 21, "short_name": "f", "declarations": [], - "spell": "7:21-7:22|0|1|2", - "extent": "7:1-7:22|0|1|0", - "type": 3231449734830406187, + "spell": "7:21-7:22|0|1|2|-1", + "extent": "7:1-7:22|0|1|0|-1", + "type": 218068462278884837, "uses": [], "kind": 13, "storage": 0 @@ -382,8 +329,8 @@ OUTPUT: "qual_name_offset": 11, "short_name": "vz1", "declarations": [], - "spell": "32:12-32:15|0|1|2", - "extent": "32:1-32:15|0|1|0", + "spell": "32:12-32:15|0|1|2|-1", + "extent": "32:1-32:15|0|1|0|-1", "type": 15440970074034693939, "uses": [], "kind": 13, @@ -395,8 +342,8 @@ OUTPUT: "short_name": "Enum1", "hover": "Enum1 = 1", "declarations": [], - "spell": "36:10-36:15|9201299975592934124|2|1026", - "extent": "36:10-36:15|9201299975592934124|2|0", + "spell": "36:10-36:15|9201299975592934124|2|1026|-1", + "extent": "36:10-36:15|9201299975592934124|2|0|-1", "type": 0, "uses": [], "kind": 22, @@ -407,9 +354,9 @@ OUTPUT: "qual_name_offset": 13, "short_name": "vc", "declarations": [], - "spell": "30:14-30:16|0|1|2", - "extent": "30:1-30:16|0|1|0", - "type": 13322943937025195708, + "spell": "30:14-30:16|0|1|2|-1", + "extent": "30:1-30:16|0|1|0|-1", + "type": 7440942986741176606, "uses": [], "kind": 13, "storage": 0 @@ -420,10 +367,10 @@ OUTPUT: "short_name": "kOnst", "hover": "static const int kOnst = 7", "declarations": [], - "spell": "41:18-41:23|0|1|2", - "extent": "41:1-41:27|0|1|0", + "spell": "41:18-41:23|0|1|2|-1", + "extent": "41:1-41:27|0|1|0|-1", "type": 53, - "uses": ["43:27-43:32|0|1|12"], + "uses": ["43:27-43:32|0|1|12|-1"], "kind": 13, "storage": 2 }, { @@ -433,10 +380,10 @@ OUTPUT: "short_name": "Enum0", "hover": "Enum0 = 0", "declarations": [], - "spell": "36:3-36:8|9201299975592934124|2|1026", - "extent": "36:3-36:8|9201299975592934124|2|0", + "spell": "36:3-36:8|9201299975592934124|2|1026|-1", + "extent": "36:3-36:8|9201299975592934124|2|0|-1", "type": 0, - "uses": ["43:20-43:25|0|1|4"], + "uses": ["43:20-43:25|0|1|4|-1"], "kind": 22, "storage": 0 }, { @@ -445,8 +392,8 @@ OUTPUT: "qual_name_offset": 11, "short_name": "vz2", "declarations": [], - "spell": "33:12-33:15|0|1|2", - "extent": "33:1-33:15|0|1|0", + "spell": "33:12-33:15|0|1|2|-1", + "extent": "33:1-33:15|0|1|0|-1", "type": 1663022413889915338, "uses": [], "kind": 13, @@ -457,8 +404,8 @@ OUTPUT: "qual_name_offset": 2, "short_name": "Value", "declarations": [], - "spell": "39:12-39:17|17498190318698490707|3|1026", - "extent": "39:10-39:17|17498190318698490707|3|0", + "spell": "39:12-39:17|17498190318698490707|3|1026|-1", + "extent": "39:10-39:17|17498190318698490707|3|0|-1", "type": 14111105212951082474, "uses": [], "kind": 253, diff --git a/index_tests/templates/specialized_func_definition.cc b/index_tests/templates/specialized_func_definition.cc index 07c0d475..1397ba80 100644 --- a/index_tests/templates/specialized_func_definition.cc +++ b/index_tests/templates/specialized_func_definition.cc @@ -24,14 +24,14 @@ OUTPUT: "skipped_ranges": [], "usr2func": [{ "usr": 6995843774014807426, - "detailed_name": "template <> void Template::Foo()", - "qual_name_offset": 31, + "detailed_name": "void Template::Foo()", + "qual_name_offset": 5, "short_name": "Foo", "kind": 6, "storage": 0, "declarations": [], - "spell": "10:22-10:25|17649312483543982122|2|1026", - "extent": "9:1-10:30|17649312483543982122|2|0", + "spell": "10:22-10:25|17649312483543982122|2|1026|-1", + "extent": "9:1-10:30|17649312483543982122|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -44,9 +44,9 @@ OUTPUT: "short_name": "Foo", "kind": 6, "storage": 0, - "declarations": ["3:8-3:11|17107291254533526269|2|1025"], - "spell": "7:19-7:22|17107291254533526269|2|1026", - "extent": "6:1-7:24|17107291254533526269|2|0", + "declarations": ["3:8-3:11|3:3-3:13|17107291254533526269|2|1025|-1"], + "spell": "7:19-7:22|17107291254533526269|2|1026|-1", + "extent": "6:1-7:24|17107291254533526269|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -60,8 +60,8 @@ OUTPUT: "short_name": "Template", "kind": 5, "declarations": [], - "spell": "2:7-2:15|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:7-2:15|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -69,7 +69,7 @@ OUTPUT: "funcs": [11994188353303124840], "vars": [], "instances": [], - "uses": ["7:6-7:14|0|1|4", "10:6-10:14|0|1|4"] + "uses": ["7:6-7:14|0|1|4|-1", "10:6-10:14|0|1|4|-1"] }, { "usr": 17649312483543982122, "detailed_name": "", diff --git a/index_tests/templates/template_class_func_usage_folded_into_one.cc b/index_tests/templates/template_class_func_usage_folded_into_one.cc index 93d12998..2297d996 100644 --- a/index_tests/templates/template_class_func_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_func_usage_folded_into_one.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 254, "storage": 0, "declarations": [], - "spell": "3:14-3:17|10528472276654770367|2|1026", - "extent": "3:3-5:4|10528472276654770367|2|0", + "spell": "3:14-3:17|10528472276654770367|2|1026|-1", + "extent": "3:3-5:4|10528472276654770367|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:19-8:22|0|1|36", "9:20-9:23|0|1|36"], + "uses": ["8:19-8:22|0|1|36|-1", "9:20-9:23|0|1|36|-1"], "callees": [] }], "usr2type": [{ @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "2:8-2:11|0|1|2", - "extent": "2:1-6:2|0|1|0", + "spell": "2:8-2:11|0|1|2|-1", + "extent": "2:1-6:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [8340731781048851399], "vars": [], "instances": [], - "uses": ["8:9-8:12|0|1|4", "9:9-9:12|0|1|4"] + "uses": ["8:9-8:12|0|1|4|-1", "9:9-9:12|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -69,8 +69,8 @@ OUTPUT: "short_name": "b", "hover": "int b = Foo::foo()", "declarations": [], - "spell": "9:5-9:6|0|1|2", - "extent": "9:1-9:25|0|1|0", + "spell": "9:5-9:6|0|1|2|-1", + "extent": "9:1-9:25|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -82,8 +82,8 @@ OUTPUT: "short_name": "a", "hover": "int a = Foo::foo()", "declarations": [], - "spell": "8:5-8:6|0|1|2", - "extent": "8:1-8:24|0|1|0", + "spell": "8:5-8:6|0|1|2|-1", + "extent": "8:1-8:24|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_class_template_func_usage_folded_into_one.cc b/index_tests/templates/template_class_template_func_usage_folded_into_one.cc index a38322c3..3fcb3672 100644 --- a/index_tests/templates/template_class_template_func_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_template_func_usage_folded_into_one.cc @@ -22,12 +22,12 @@ OUTPUT: "kind": 254, "storage": 0, "declarations": [], - "spell": "4:14-4:17|10528472276654770367|2|1026", - "extent": "4:3-6:4|10528472276654770367|2|0", + "spell": "4:14-4:17|10528472276654770367|2|1026|-1", + "extent": "4:3-6:4|10528472276654770367|2|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["9:19-9:22|0|1|36", "10:20-10:23|0|1|36"], + "uses": ["9:19-9:22|0|1|36|-1", "10:20-10:23|0|1|36|-1"], "callees": [] }], "usr2type": [{ @@ -52,8 +52,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "2:8-2:11|0|1|2", - "extent": "2:1-7:2|0|1|0", + "spell": "2:8-2:11|0|1|2|-1", + "extent": "2:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -61,7 +61,7 @@ OUTPUT: "funcs": [9034026360701857235], "vars": [], "instances": [], - "uses": ["9:9-9:12|0|1|4", "10:9-10:12|0|1|4"] + "uses": ["9:9-9:12|0|1|4|-1", "10:9-10:12|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -70,8 +70,8 @@ OUTPUT: "short_name": "b", "hover": "int b = Foo::foo()", "declarations": [], - "spell": "10:5-10:6|0|1|2", - "extent": "10:1-10:33|0|1|0", + "spell": "10:5-10:6|0|1|2|-1", + "extent": "10:1-10:33|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -83,8 +83,8 @@ OUTPUT: "short_name": "a", "hover": "int a = Foo::foo()", "declarations": [], - "spell": "9:5-9:6|0|1|2", - "extent": "9:1-9:31|0|1|0", + "spell": "9:5-9:6|0|1|2|-1", + "extent": "9:1-9:31|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_class_type_usage_folded_into_one.cc b/index_tests/templates/template_class_type_usage_folded_into_one.cc index 0dbec81c..09bc2e7c 100644 --- a/index_tests/templates/template_class_type_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_type_usage_folded_into_one.cc @@ -35,13 +35,13 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 6697181287623958829, - "detailed_name": "enum A {\n}", + "detailed_name": "enum A {}", "qual_name_offset": 5, "short_name": "A", "kind": 10, "declarations": [], - "spell": "1:6-1:7|0|1|2", - "extent": "1:1-1:10|0|1|0", + "spell": "1:6-1:7|0|1|2|-1", + "extent": "1:1-1:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -49,24 +49,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:5-9:6|0|1|4"] - }, { - "usr": 7074603899792463171, - "detailed_name": "Inner", - "qual_name_offset": 0, - "short_name": "Inner", - "kind": 26, - "declarations": [], - "spell": "6:10-6:15|0|1|2", - "extent": "6:3-6:18|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [16721564935990383768], - "uses": [] + "uses": ["9:5-9:6|0|1|4|-1"] }, { "usr": 10528472276654770367, "detailed_name": "struct Foo {}", @@ -74,8 +57,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:8-5:11|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -83,16 +66,16 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:1-9:4|0|1|4", "10:1-10:4|0|1|4"] + "uses": ["9:1-9:4|0|1|4|-1", "10:1-10:4|0|1|4|-1"] }, { "usr": 13892793056005362145, - "detailed_name": "enum B {\n}", + "detailed_name": "enum B {}", "qual_name_offset": 5, "short_name": "B", "kind": 10, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-2:10|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-2:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -100,7 +83,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:5-10:6|0|1|4"] + "uses": ["10:5-10:6|0|1|4|-1"] }, { "usr": 13938528237873543349, "detailed_name": "struct Foo::Inner {}", @@ -108,33 +91,16 @@ OUTPUT: "short_name": "Inner", "kind": 23, "declarations": [], - "spell": "6:10-6:15|10528472276654770367|2|1026", - "extent": "6:3-6:18|10528472276654770367|2|0", + "spell": "6:10-6:15|10528472276654770367|2|1026|-1", + "extent": "6:3-6:18|10528472276654770367|2|0|-1", "alias_of": 0, "bases": [], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["9:9-9:14|0|1|4", "10:9-10:14|0|1|4"] - }, { - "usr": 15961308565836244174, - "detailed_name": "Inner", - "qual_name_offset": 0, - "short_name": "Inner", - "kind": 26, - "declarations": [], - "spell": "6:10-6:15|0|1|2", - "extent": "6:3-6:18|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [12028309045033782423], - "uses": [] + "instances": [16721564935990383768, 12028309045033782423], + "uses": ["9:9-9:14|0|1|4|-1", "10:9-10:14|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -142,9 +108,9 @@ OUTPUT: "qual_name_offset": 14, "short_name": "b", "declarations": [], - "spell": "10:15-10:16|0|1|2", - "extent": "10:1-10:16|0|1|0", - "type": 15961308565836244174, + "spell": "10:15-10:16|0|1|2|-1", + "extent": "10:1-10:16|0|1|0|-1", + "type": 13938528237873543349, "uses": [], "kind": 13, "storage": 0 @@ -154,9 +120,9 @@ OUTPUT: "qual_name_offset": 14, "short_name": "a", "declarations": [], - "spell": "9:15-9:16|0|1|2", - "extent": "9:1-9:16|0|1|0", - "type": 7074603899792463171, + "spell": "9:15-9:16|0|1|2|-1", + "extent": "9:1-9:16|0|1|0|-1", + "type": 13938528237873543349, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/templates/template_class_var_usage_folded_into_one.cc b/index_tests/templates/template_class_var_usage_folded_into_one.cc index fd172671..23d2ed6a 100644 --- a/index_tests/templates/template_class_var_usage_folded_into_one.cc +++ b/index_tests/templates/template_class_var_usage_folded_into_one.cc @@ -34,8 +34,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "2:8-2:11|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:8-2:11|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["6:9-6:12|0|1|4", "7:9-7:12|0|1|4"] + "uses": ["6:9-6:12|0|1|4|-1", "7:9-7:12|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -52,8 +52,8 @@ OUTPUT: "short_name": "b", "hover": "int b = Foo::var", "declarations": [], - "spell": "7:5-7:6|0|1|2", - "extent": "7:1-7:23|0|1|0", + "spell": "7:5-7:6|0|1|2|-1", + "extent": "7:1-7:23|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -64,9 +64,9 @@ OUTPUT: "qual_name_offset": 21, "short_name": "var", "hover": "static constexpr int Foo::var = 3", - "declarations": ["3:24-3:27|10528472276654770367|2|1025"], + "declarations": ["3:24-3:27|3:3-3:31|10528472276654770367|2|1025|-1"], "type": 53, - "uses": ["6:19-6:22|0|1|12", "7:20-7:23|0|1|12"], + "uses": ["6:19-6:22|0|1|12|-1", "7:20-7:23|0|1|12|-1"], "kind": 13, "storage": 2 }, { @@ -76,8 +76,8 @@ OUTPUT: "short_name": "a", "hover": "int a = Foo::var", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:22|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:22|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_func_usage_folded_into_one.cc b/index_tests/templates/template_func_usage_folded_into_one.cc index 8fccd50a..c9329711 100644 --- a/index_tests/templates/template_func_usage_folded_into_one.cc +++ b/index_tests/templates/template_func_usage_folded_into_one.cc @@ -22,12 +22,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:12-2:15|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:12-2:15|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:9-6:12|0|1|36", "7:9-7:12|0|1|36"], + "uses": ["6:9-6:12|0|1|36|-1", "7:9-7:12|0|1|36|-1"], "callees": [] }], "usr2type": [{ @@ -53,8 +53,8 @@ OUTPUT: "short_name": "b", "hover": "int b = foo()", "declarations": [], - "spell": "7:5-7:6|0|1|2", - "extent": "7:1-7:20|0|1|0", + "spell": "7:5-7:6|0|1|2|-1", + "extent": "7:1-7:20|0|1|0|-1", "type": 53, "uses": [], "kind": 13, @@ -66,8 +66,8 @@ OUTPUT: "short_name": "a", "hover": "int a = foo()", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:19|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:19|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/templates/template_type_usage_folded_into_one.cc b/index_tests/templates/template_type_usage_folded_into_one.cc index 0c83f7d8..fb719179 100644 --- a/index_tests/templates/template_type_usage_folded_into_one.cc +++ b/index_tests/templates/template_type_usage_folded_into_one.cc @@ -11,56 +11,22 @@ OUTPUT: "skipped_ranges": [], "usr2func": [], "usr2type": [{ - "usr": 5123806965838456033, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "2:7-2:10|0|1|2", - "extent": "1:1-2:13|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [16721564935990383768], - "uses": [] - }, { "usr": 10528472276654770367, "detailed_name": "class Foo {}", "qual_name_offset": 6, "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "2:7-2:10|0|1|2", - "extent": "2:1-2:13|0|1|0", + "spell": "2:7-2:10|0|1|2|-1", + "extent": "2:1-2:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["4:1-4:4|0|1|4", "5:1-5:4|0|1|4"] - }, { - "usr": 14134940367505932005, - "detailed_name": "Foo", - "qual_name_offset": 0, - "short_name": "Foo", - "kind": 26, - "declarations": [], - "spell": "2:7-2:10|0|1|2", - "extent": "1:1-2:13|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [12028309045033782423], - "uses": [] + "instances": [16721564935990383768, 12028309045033782423], + "uses": ["4:1-4:4|0|1|4|-1", "5:1-5:4|0|1|4|-1"] }], "usr2var": [{ "usr": 12028309045033782423, @@ -68,9 +34,9 @@ OUTPUT: "qual_name_offset": 10, "short_name": "b", "declarations": [], - "spell": "5:11-5:12|0|1|2", - "extent": "5:1-5:12|0|1|0", - "type": 14134940367505932005, + "spell": "5:11-5:12|0|1|2|-1", + "extent": "5:1-5:12|0|1|0|-1", + "type": 10528472276654770367, "uses": [], "kind": 13, "storage": 0 @@ -80,9 +46,9 @@ OUTPUT: "qual_name_offset": 9, "short_name": "a", "declarations": [], - "spell": "4:10-4:11|0|1|2", - "extent": "4:1-4:11|0|1|0", - "type": 5123806965838456033, + "spell": "4:10-4:11|0|1|2|-1", + "extent": "4:1-4:11|0|1|0|-1", + "type": 10528472276654770367, "uses": [], "kind": 13, "storage": 0 diff --git a/index_tests/templates/template_var_usage_folded_into_one.cc b/index_tests/templates/template_var_usage_folded_into_one.cc index e325205d..44489203 100644 --- a/index_tests/templates/template_var_usage_folded_into_one.cc +++ b/index_tests/templates/template_var_usage_folded_into_one.cc @@ -38,13 +38,13 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 6697181287623958829, - "detailed_name": "enum A {\n}", + "detailed_name": "enum A {}", "qual_name_offset": 5, "short_name": "A", "kind": 10, "declarations": [], - "spell": "1:6-1:7|0|1|2", - "extent": "1:1-1:10|0|1|0", + "spell": "1:6-1:7|0|1|2|-1", + "extent": "1:1-1:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -52,7 +52,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [16721564935990383768], - "uses": ["7:1-7:2|0|1|4", "7:11-7:12|0|1|4"] + "uses": ["7:1-7:2|0|1|4|-1", "7:11-7:12|0|1|4|-1"] }, { "usr": 11919899838872947844, "detailed_name": "T", @@ -60,8 +60,8 @@ OUTPUT: "short_name": "T", "kind": 26, "declarations": [], - "spell": "4:19-4:20|0|1|2", - "extent": "4:10-4:20|0|1|0", + "spell": "4:19-4:20|0|1|2|-1", + "extent": "4:10-4:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -72,13 +72,13 @@ OUTPUT: "uses": [] }, { "usr": 13892793056005362145, - "detailed_name": "enum B {\n}", + "detailed_name": "enum B {}", "qual_name_offset": 5, "short_name": "B", "kind": 10, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-2:10|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-2:10|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -86,7 +86,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [12028309045033782423], - "uses": ["8:1-8:2|0|1|4", "8:11-8:12|0|1|4"] + "uses": ["8:1-8:2|0|1|4|-1", "8:11-8:12|0|1|4|-1"] }], "usr2var": [{ "usr": 8096973118640070624, @@ -95,10 +95,10 @@ OUTPUT: "short_name": "var", "hover": "T var = T()", "declarations": [], - "spell": "5:3-5:6|0|1|2", - "extent": "5:1-5:12|0|1|0", + "spell": "5:3-5:6|0|1|2|-1", + "extent": "5:1-5:12|0|1|0|-1", "type": 11919899838872947844, - "uses": ["7:7-7:10|0|1|12", "8:7-8:10|0|1|12"], + "uses": ["7:7-7:10|0|1|12|-1", "8:7-8:10|0|1|12|-1"], "kind": 13, "storage": 0 }, { @@ -108,8 +108,8 @@ OUTPUT: "short_name": "b", "hover": "B b = var", "declarations": [], - "spell": "8:3-8:4|0|1|2", - "extent": "8:1-8:13|0|1|0", + "spell": "8:3-8:4|0|1|2|-1", + "extent": "8:1-8:13|0|1|0|-1", "type": 13892793056005362145, "uses": [], "kind": 13, @@ -121,8 +121,8 @@ OUTPUT: "short_name": "a", "hover": "A a = var", "declarations": [], - "spell": "7:3-7:4|0|1|2", - "extent": "7:1-7:13|0|1|0", + "spell": "7:3-7:4|0|1|2|-1", + "extent": "7:1-7:13|0|1|0|-1", "type": 6697181287623958829, "uses": [], "kind": 13, diff --git a/index_tests/types/anonymous_struct.cc b/index_tests/types/anonymous_struct.cc index 8a75ecf9..9d88a8bf 100644 --- a/index_tests/types/anonymous_struct.cc +++ b/index_tests/types/anonymous_struct.cc @@ -26,13 +26,13 @@ OUTPUT: "uses": [] }, { "usr": 1428566502523368801, - "detailed_name": "struct {}", + "detailed_name": "anon struct", "qual_name_offset": 0, - "short_name": "", + "short_name": "anon struct", "kind": 23, "declarations": [], - "spell": "2:3-2:9|17937907487590875128|2|1026", - "extent": "2:3-2:28|17937907487590875128|2|0", + "spell": "2:3-2:9|17937907487590875128|2|1026|-1", + "extent": "2:3-2:28|17937907487590875128|2|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -57,8 +57,8 @@ OUTPUT: "short_name": "vector3", "kind": 5, "declarations": [], - "spell": "1:7-1:14|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:14|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -86,8 +86,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "v", "declarations": [], - "spell": "3:9-3:10|17937907487590875128|2|1026", - "extent": "3:3-3:13|17937907487590875128|2|0", + "spell": "3:9-3:10|17937907487590875128|2|1026|-1", + "extent": "3:3-3:13|17937907487590875128|2|0|-1", "type": 0, "uses": [], "kind": 8, @@ -98,8 +98,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "x", "declarations": [], - "spell": "2:18-2:19|1428566502523368801|2|1026", - "extent": "2:12-2:19|1428566502523368801|2|0", + "spell": "2:18-2:19|1428566502523368801|2|1026|-1", + "extent": "2:12-2:19|1428566502523368801|2|0|-1", "type": 82, "uses": [], "kind": 8, @@ -110,8 +110,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "y", "declarations": [], - "spell": "2:21-2:22|1428566502523368801|2|1026", - "extent": "2:12-2:22|1428566502523368801|2|0", + "spell": "2:21-2:22|1428566502523368801|2|1026|-1", + "extent": "2:12-2:22|1428566502523368801|2|0|-1", "type": 82, "uses": [], "kind": 8, @@ -122,8 +122,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "z", "declarations": [], - "spell": "2:24-2:25|1428566502523368801|2|1026", - "extent": "2:12-2:25|1428566502523368801|2|0", + "spell": "2:24-2:25|1428566502523368801|2|1026|-1", + "extent": "2:12-2:25|1428566502523368801|2|0|-1", "type": 82, "uses": [], "kind": 8, diff --git a/index_tests/types/typedefs.cc b/index_tests/types/typedefs.cc index 38505c29..17d3fcbd 100644 --- a/index_tests/types/typedefs.cc +++ b/index_tests/types/typedefs.cc @@ -13,7 +13,7 @@ OUTPUT: "short_name": "g", "kind": 12, "storage": 0, - "declarations": ["2:13-2:14|0|1|1"], + "declarations": ["2:13-2:14|2:1-2:14|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -27,8 +27,8 @@ OUTPUT: "short_name": "func", "kind": 252, "declarations": [], - "spell": "1:14-1:18|0|1|2", - "extent": "1:1-1:47|0|1|0", + "spell": "1:14-1:18|0|1|2|-1", + "extent": "1:1-1:47|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -36,7 +36,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:8-2:12|0|1|4"] + "uses": ["2:8-2:12|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/unions/union_decl.cc b/index_tests/unions/union_decl.cc index 83b94e90..7861f8ff 100644 --- a/index_tests/unions/union_decl.cc +++ b/index_tests/unions/union_decl.cc @@ -46,8 +46,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -69,8 +69,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "b", "declarations": [], - "spell": "3:8-3:9|8501689086387244262|2|1026", - "extent": "3:3-3:9|8501689086387244262|2|0", + "spell": "3:8-3:9|8501689086387244262|2|1026|-1", + "extent": "3:3-3:9|8501689086387244262|2|0|-1", "type": 37, "uses": [], "kind": 8, @@ -81,8 +81,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|8501689086387244262|2|1026", - "extent": "2:3-2:8|8501689086387244262|2|0", + "spell": "2:7-2:8|8501689086387244262|2|1026|-1", + "extent": "2:3-2:8|8501689086387244262|2|0|-1", "type": 53, "uses": [], "kind": 8, diff --git a/index_tests/unions/union_usage.cc b/index_tests/unions/union_usage.cc index 253c4a34..248f5975 100644 --- a/index_tests/unions/union_usage.cc +++ b/index_tests/unions/union_usage.cc @@ -24,8 +24,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:9|0|1|2", - "extent": "8:1-10:2|0|1|0", + "spell": "8:6-8:9|0|1|2|-1", + "extent": "8:1-10:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -69,8 +69,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -84,7 +84,7 @@ OUTPUT: "R": 0 }], "instances": [2933643612409209903], - "uses": ["6:1-6:4|0|1|4", "8:10-8:13|0|1|4"] + "uses": ["6:1-6:4|0|1|4|-1", "8:10-8:13|0|1|4|-1"] }], "usr2var": [{ "usr": 2933643612409209903, @@ -92,10 +92,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "6:5-6:6|0|1|2", - "extent": "6:1-6:6|0|1|0", + "spell": "6:5-6:6|0|1|2|-1", + "extent": "6:1-6:6|0|1|0|-1", "type": 8501689086387244262, - "uses": ["9:3-9:4|13982179977217945200|3|4"], + "uses": ["9:3-9:4|13982179977217945200|3|4|-1"], "kind": 13, "storage": 0 }, { @@ -104,8 +104,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "b", "declarations": [], - "spell": "3:8-3:9|8501689086387244262|2|1026", - "extent": "3:3-3:13|8501689086387244262|2|0", + "spell": "3:8-3:9|8501689086387244262|2|1026|-1", + "extent": "3:3-3:13|8501689086387244262|2|0|-1", "type": 37, "uses": [], "kind": 8, @@ -116,10 +116,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|8501689086387244262|2|1026", - "extent": "2:3-2:12|8501689086387244262|2|0", + "spell": "2:7-2:8|8501689086387244262|2|1026|-1", + "extent": "2:3-2:12|8501689086387244262|2|0|-1", "type": 53, - "uses": ["9:5-9:6|13982179977217945200|3|20"], + "uses": ["9:5-9:6|13982179977217945200|3|20|-1"], "kind": 8, "storage": 0 }] diff --git a/index_tests/usage/func_called_from_constructor.cc b/index_tests/usage/func_called_from_constructor.cc index 69269d9e..53c43669 100644 --- a/index_tests/usage/func_called_from_constructor.cc +++ b/index_tests/usage/func_called_from_constructor.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:12|0|1|2", - "extent": "1:1-1:17|0|1|0", + "spell": "1:6-1:12|0|1|2|-1", + "extent": "1:1-1:17|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:3-8:9|3385168158331140247|3|16420"], + "uses": ["8:3-8:9|3385168158331140247|3|16420|-1"], "callees": [] }, { "usr": 3385168158331140247, @@ -35,9 +35,9 @@ OUTPUT: "short_name": "Foo", "kind": 9, "storage": 0, - "declarations": ["4:3-4:6|15041163540773201510|2|1025"], - "spell": "7:6-7:9|15041163540773201510|2|1026", - "extent": "7:1-9:2|15041163540773201510|2|0", + "declarations": ["4:3-4:6|4:3-4:8|15041163540773201510|2|1025|-1"], + "spell": "7:6-7:9|15041163540773201510|2|1026|-1", + "extent": "7:1-9:2|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "3:8-3:11|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:8-3:11|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [3385168158331140247], "vars": [], "instances": [], - "uses": ["4:3-4:6|15041163540773201510|2|4", "7:1-7:4|0|1|4", "7:6-7:9|15041163540773201510|2|4"] + "uses": ["4:3-4:6|15041163540773201510|2|4|-1", "7:1-7:4|0|1|4|-1", "7:6-7:9|15041163540773201510|2|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/func_called_from_macro_argument.cc b/index_tests/usage/func_called_from_macro_argument.cc index 1312ef95..868db9e8 100644 --- a/index_tests/usage/func_called_from_macro_argument.cc +++ b/index_tests/usage/func_called_from_macro_argument.cc @@ -18,11 +18,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["3:6-3:12|0|1|1"], + "declarations": ["3:6-3:12|3:1-3:28|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["6:14-6:20|11404881820527069090|3|16420", "6:14-6:20|0|1|64|0"], + "uses": ["6:14-6:20|11404881820527069090|3|16420|-1", "6:14-6:20|0|1|64|0"], "callees": [] }, { "usr": 11404881820527069090, @@ -32,8 +32,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:12|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:6-5:12|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -48,10 +48,10 @@ OUTPUT: "short_name": "MACRO_CALL", "hover": "#define MACRO_CALL(e) e", "declarations": [], - "spell": "1:9-1:19|0|1|2", - "extent": "1:9-1:24|0|1|0", + "spell": "1:9-1:19|0|1|2|-1", + "extent": "1:9-1:24|0|1|0|-1", "type": 0, - "uses": ["6:3-6:13|0|1|64"], + "uses": ["6:3-6:13|0|1|64|-1"], "kind": 255, "storage": 0 }] diff --git a/index_tests/usage/func_called_from_template.cc b/index_tests/usage/func_called_from_template.cc index becca51b..0d223bec 100644 --- a/index_tests/usage/func_called_from_template.cc +++ b/index_tests/usage/func_called_from_template.cc @@ -23,11 +23,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["1:6-1:12|0|1|1"], + "declarations": ["1:6-1:12|1:1-1:14|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["5:3-5:9|10177235824697315808|3|16420"], + "uses": ["5:3-5:9|10177235824697315808|3|16420|-1"], "callees": [] }, { "usr": 2459767597003442547, @@ -50,8 +50,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:9|0|1|2", - "extent": "8:1-10:2|0|1|0", + "spell": "8:6-8:9|0|1|2|-1", + "extent": "8:1-10:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -65,12 +65,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:12|0|1|2", - "extent": "4:1-6:2|0|1|0", + "spell": "4:6-4:12|0|1|2|-1", + "extent": "4:1-6:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["9:3-9:9|4259594751088586730|3|16420"], + "uses": ["9:3-9:9|4259594751088586730|3|16420|-1"], "callees": ["5:3-5:9|468307235068920063|3|16420"] }], "usr2type": [], diff --git a/index_tests/usage/func_called_implicit_ctor.cc b/index_tests/usage/func_called_implicit_ctor.cc index 522158bd..63a13f2b 100644 --- a/index_tests/usage/func_called_implicit_ctor.cc +++ b/index_tests/usage/func_called_implicit_ctor.cc @@ -21,12 +21,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:5-5:11|0|1|2", - "extent": "5:1-5:27|0|1|0", + "spell": "5:5-5:11|0|1|2|-1", + "extent": "5:1-5:27|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["8:10-8:16|11404881820527069090|3|16420"], + "uses": ["8:10-8:16|11404881820527069090|3|16420|-1"], "callees": [] }, { "usr": 10544127002917214589, @@ -35,11 +35,11 @@ OUTPUT: "short_name": "Wrapper", "kind": 9, "storage": 0, - "declarations": ["2:3-2:10|13611487872560323389|2|1025"], + "declarations": ["2:3-2:10|2:3-2:17|13611487872560323389|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["8:10-8:16|11404881820527069090|3|16676"], + "uses": ["8:10-8:16|11404881820527069090|3|16676|-1"], "callees": [] }, { "usr": 11404881820527069090, @@ -49,8 +49,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:9-7:15|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:9-7:15|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -64,8 +64,8 @@ OUTPUT: "short_name": "Wrapper", "kind": 23, "declarations": [], - "spell": "1:8-1:15|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:15|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -73,7 +73,7 @@ OUTPUT: "funcs": [10544127002917214589], "vars": [], "instances": [], - "uses": ["2:3-2:10|13611487872560323389|2|4", "7:1-7:8|0|1|4"] + "uses": ["2:3-2:10|13611487872560323389|2|4|-1", "7:1-7:8|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/func_usage_addr_func.cc b/index_tests/usage/func_usage_addr_func.cc index 294b6f5e..9d4efdb6 100644 --- a/index_tests/usage/func_usage_addr_func.cc +++ b/index_tests/usage/func_usage_addr_func.cc @@ -20,12 +20,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:10|0|1|2", - "extent": "3:1-3:15|0|1|0", + "spell": "3:6-3:10|0|1|2|-1", + "extent": "3:1-3:15|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:18-6:22|9376923949268137283|3|132", "7:12-7:16|9376923949268137283|3|132"], + "uses": ["6:18-6:22|9376923949268137283|3|132|-1", "7:12-7:16|9376923949268137283|3|132|-1"], "callees": [] }, { "usr": 9376923949268137283, @@ -35,8 +35,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [16088407831770615719], @@ -50,12 +50,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:13|0|1|2", - "extent": "1:1-1:28|0|1|0", + "spell": "1:6-1:13|0|1|2|-1", + "extent": "1:1-1:28|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["7:3-7:10|9376923949268137283|3|16420"], + "uses": ["7:3-7:10|9376923949268137283|3|16420|-1"], "callees": [] }], "usr2type": [], @@ -66,8 +66,8 @@ OUTPUT: "short_name": "x", "hover": "void (*x)() = &used", "declarations": [], - "spell": "6:10-6:11|9376923949268137283|3|2", - "extent": "6:3-6:22|9376923949268137283|3|0", + "spell": "6:10-6:11|9376923949268137283|3|2|-1", + "extent": "6:3-6:22|9376923949268137283|3|0|-1", "type": 0, "uses": [], "kind": 13, diff --git a/index_tests/usage/func_usage_addr_method.cc b/index_tests/usage/func_usage_addr_method.cc index 3dfdda35..e8242960 100644 --- a/index_tests/usage/func_usage_addr_method.cc +++ b/index_tests/usage/func_usage_addr_method.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [4636142131003982569], @@ -34,11 +34,11 @@ OUTPUT: "short_name": "Used", "kind": 6, "storage": 0, - "declarations": ["2:8-2:12|15041163540773201510|2|1025"], + "declarations": ["2:8-2:12|2:3-2:14|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["6:18-6:22|9376923949268137283|3|132"], + "uses": ["6:18-6:22|9376923949268137283|3|132|-1"], "callees": [] }], "usr2type": [{ @@ -48,8 +48,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -57,7 +57,7 @@ OUTPUT: "funcs": [18417145003926999463], "vars": [], "instances": [], - "uses": ["6:13-6:16|9376923949268137283|3|4"] + "uses": ["6:13-6:16|9376923949268137283|3|4|-1"] }], "usr2var": [{ "usr": 4636142131003982569, @@ -66,8 +66,8 @@ OUTPUT: "short_name": "x", "hover": "void (Foo::*)() x = &Foo::Used", "declarations": [], - "spell": "6:8-6:9|9376923949268137283|3|2", - "extent": "6:3-6:22|9376923949268137283|3|0", + "spell": "6:8-6:9|9376923949268137283|3|2|-1", + "extent": "6:3-6:22|9376923949268137283|3|0|-1", "type": 0, "uses": [], "kind": 13, diff --git a/index_tests/usage/func_usage_call_func.cc b/index_tests/usage/func_usage_call_func.cc index b6d82740..0ec91f0a 100644 --- a/index_tests/usage/func_usage_call_func.cc +++ b/index_tests/usage/func_usage_call_func.cc @@ -16,12 +16,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:12|0|1|2", - "extent": "1:1-1:17|0|1|0", + "spell": "1:6-1:12|0|1|2|-1", + "extent": "1:1-1:17|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["3:3-3:9|11404881820527069090|3|16420"], + "uses": ["3:3-3:9|11404881820527069090|3|16420|-1"], "callees": [] }, { "usr": 11404881820527069090, @@ -31,8 +31,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:12|0|1|2", - "extent": "2:1-4:2|0|1|0", + "spell": "2:6-2:12|0|1|2|-1", + "extent": "2:1-4:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/usage/func_usage_call_method.cc b/index_tests/usage/func_usage_call_method.cc index e16be451..726f13fd 100644 --- a/index_tests/usage/func_usage_call_method.cc +++ b/index_tests/usage/func_usage_call_method.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:10|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:10|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [14045150712868309451], @@ -34,11 +34,11 @@ OUTPUT: "short_name": "Used", "kind": 6, "storage": 0, - "declarations": ["2:8-2:12|15041163540773201510|2|1025"], + "declarations": ["2:8-2:12|2:3-2:14|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["7:6-7:10|9376923949268137283|3|16420"], + "uses": ["7:6-7:10|9376923949268137283|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -48,8 +48,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -57,7 +57,7 @@ OUTPUT: "funcs": [18417145003926999463], "vars": [], "instances": [14045150712868309451], - "uses": ["6:3-6:6|9376923949268137283|3|4"] + "uses": ["6:3-6:6|9376923949268137283|3|4|-1"] }], "usr2var": [{ "usr": 14045150712868309451, @@ -66,10 +66,10 @@ OUTPUT: "short_name": "f", "hover": "Foo *f = nullptr", "declarations": [], - "spell": "6:8-6:9|9376923949268137283|3|2", - "extent": "6:3-6:19|9376923949268137283|3|0", + "spell": "6:8-6:9|9376923949268137283|3|2|-1", + "extent": "6:3-6:19|9376923949268137283|3|0|-1", "type": 15041163540773201510, - "uses": ["7:3-7:4|9376923949268137283|3|12"], + "uses": ["7:3-7:4|9376923949268137283|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/func_usage_class_inline_var_def.cc b/index_tests/usage/func_usage_class_inline_var_def.cc index 41392385..6872016b 100644 --- a/index_tests/usage/func_usage_class_inline_var_def.cc +++ b/index_tests/usage/func_usage_class_inline_var_def.cc @@ -19,12 +19,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:12-1:18|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:12-1:18|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:11-6:17|15041163540773201510|2|36"], + "uses": ["6:11-6:17|15041163540773201510|2|36|-1"], "callees": [] }], "usr2type": [{ @@ -49,8 +49,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "5:7-5:10|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:7-5:10|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -70,8 +70,8 @@ OUTPUT: "short_name": "x", "hover": "int Foo::x = helper()", "declarations": [], - "spell": "6:7-6:8|15041163540773201510|2|1026", - "extent": "6:3-6:19|15041163540773201510|2|0", + "spell": "6:7-6:8|15041163540773201510|2|1026|-1", + "extent": "6:3-6:19|15041163540773201510|2|0|-1", "type": 53, "uses": [], "kind": 8, diff --git a/index_tests/usage/func_usage_forward_decl_func.cc b/index_tests/usage/func_usage_forward_decl_func.cc index 775595fd..1e7cef98 100644 --- a/index_tests/usage/func_usage_forward_decl_func.cc +++ b/index_tests/usage/func_usage_forward_decl_func.cc @@ -15,11 +15,11 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["1:6-1:9|0|1|1"], + "declarations": ["1:6-1:9|1:1-1:11|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["4:3-4:6|6767773193109753523|3|16420"], + "uses": ["4:3-4:6|6767773193109753523|3|16420|-1"], "callees": [] }, { "usr": 6767773193109753523, @@ -29,8 +29,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:11|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:11|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/usage/func_usage_forward_decl_method.cc b/index_tests/usage/func_usage_forward_decl_method.cc index d27dadec..9fdfb1ed 100644 --- a/index_tests/usage/func_usage_forward_decl_method.cc +++ b/index_tests/usage/func_usage_forward_decl_method.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:11|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:6-5:11|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [16229832321010999607], @@ -33,11 +33,11 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["2:8-2:11|15041163540773201510|2|1025"], + "declarations": ["2:8-2:11|2:3-2:13|15041163540773201510|2|1025|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["7:6-7:9|6767773193109753523|3|16420"], + "uses": ["7:6-7:9|6767773193109753523|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -47,8 +47,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -56,7 +56,7 @@ OUTPUT: "funcs": [17922201480358737771], "vars": [], "instances": [16229832321010999607], - "uses": ["6:3-6:6|6767773193109753523|3|4"] + "uses": ["6:3-6:6|6767773193109753523|3|4|-1"] }], "usr2var": [{ "usr": 16229832321010999607, @@ -65,10 +65,10 @@ OUTPUT: "short_name": "f", "hover": "Foo *f = nullptr", "declarations": [], - "spell": "6:8-6:9|6767773193109753523|3|2", - "extent": "6:3-6:19|6767773193109753523|3|0", + "spell": "6:8-6:9|6767773193109753523|3|2|-1", + "extent": "6:3-6:19|6767773193109753523|3|0|-1", "type": 15041163540773201510, - "uses": ["7:3-7:4|6767773193109753523|3|12"], + "uses": ["7:3-7:4|6767773193109753523|3|12|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/func_usage_template_func.cc b/index_tests/usage/func_usage_template_func.cc index 422d5952..72e6e670 100644 --- a/index_tests/usage/func_usage_template_func.cc +++ b/index_tests/usage/func_usage_template_func.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-7:2|0|1|0", + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -33,11 +33,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["2:6-2:12|0|1|1"], + "declarations": ["2:6-2:12|2:1-2:15|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["5:3-5:9|4259594751088586730|3|16420", "6:3-6:9|4259594751088586730|3|16420"], + "uses": ["5:3-5:9|4259594751088586730|3|16420|-1", "6:3-6:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/usage/type_usage_as_template_parameter.cc b/index_tests/usage/type_usage_as_template_parameter.cc index 74d2c025..169d5ad4 100644 --- a/index_tests/usage/type_usage_as_template_parameter.cc +++ b/index_tests/usage/type_usage_as_template_parameter.cc @@ -23,8 +23,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "9:16-9:27|0|1|2", - "extent": "9:1-12:2|0|1|0", + "spell": "9:16-9:27|0|1|2|-1", + "extent": "9:1-12:2|0|1|0|-1", "bases": [], "derived": [], "vars": [3364438781074774169], @@ -38,33 +38,16 @@ OUTPUT: "short_name": "unique_ptr", "kind": 5, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "2:1-2:20|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "2:1-2:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], "types": [], "funcs": [], "vars": [], - "instances": [], - "uses": ["6:8-6:18|0|1|4", "7:8-7:18|0|1|4", "9:1-9:11|0|1|4", "10:3-10:13|16359708726068806331|3|4"] - }, { - "usr": 4186953406371619898, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, - "short_name": "unique_ptr", - "kind": 26, - "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:20|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [18075066956054788088, 3364438781074774169], - "uses": [] + "instances": [12857919739649552168, 18075066956054788088, 3364438781074774169], + "uses": ["6:8-6:18|0|1|4|-1", "7:8-7:18|0|1|4|-1", "9:1-9:11|0|1|4|-1", "10:3-10:13|16359708726068806331|3|4|-1"] }, { "usr": 4750332761459066907, "detailed_name": "struct S {}", @@ -72,8 +55,8 @@ OUTPUT: "short_name": "S", "kind": 23, "declarations": [], - "spell": "4:8-4:9|0|1|2", - "extent": "4:1-4:12|0|1|0", + "spell": "4:8-4:9|0|1|2|-1", + "extent": "4:1-4:12|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -81,24 +64,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["7:19-7:20|0|1|4", "9:12-9:13|0|1|4", "10:14-10:15|16359708726068806331|3|4"] - }, { - "usr": 16848604152578034754, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, - "short_name": "unique_ptr", - "kind": 26, - "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:20|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [12857919739649552168], - "uses": [] + "uses": ["7:19-7:20|0|1|4|-1", "9:12-9:13|0|1|4|-1", "10:14-10:15|16359708726068806331|3|4|-1"] }], "usr2var": [{ "usr": 3364438781074774169, @@ -106,9 +72,9 @@ OUTPUT: "qual_name_offset": 15, "short_name": "local", "declarations": [], - "spell": "10:18-10:23|16359708726068806331|3|2", - "extent": "10:3-10:23|16359708726068806331|3|0", - "type": 4186953406371619898, + "spell": "10:18-10:23|16359708726068806331|3|2|-1", + "extent": "10:3-10:23|16359708726068806331|3|0|-1", + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 0 @@ -118,9 +84,9 @@ OUTPUT: "qual_name_offset": 24, "short_name": "f0", "declarations": [], - "spell": "6:25-6:27|0|1|2", - "extent": "6:1-6:27|0|1|0", - "type": 16848604152578034754, + "spell": "6:25-6:27|0|1|2|-1", + "extent": "6:1-6:27|0|1|0|-1", + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 2 @@ -130,9 +96,9 @@ OUTPUT: "qual_name_offset": 21, "short_name": "f1", "declarations": [], - "spell": "7:22-7:24|0|1|2", - "extent": "7:1-7:24|0|1|0", - "type": 4186953406371619898, + "spell": "7:22-7:24|0|1|2|-1", + "extent": "7:1-7:24|0|1|0|-1", + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 2 diff --git a/index_tests/usage/type_usage_as_template_parameter_complex.cc b/index_tests/usage/type_usage_as_template_parameter_complex.cc index 7b5ebc54..3ed6d40d 100644 --- a/index_tests/usage/type_usage_as_template_parameter_complex.cc +++ b/index_tests/usage/type_usage_as_template_parameter_complex.cc @@ -91,8 +91,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "33:37-33:51|0|1|2", - "extent": "33:1-33:92|0|1|0", + "spell": "33:37-33:51|0|1|2|-1", + "extent": "33:1-33:92|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -106,8 +106,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "40:6-40:20|0|1|2", - "extent": "40:1-40:28|0|1|0", + "spell": "40:6-40:20|0|1|2|-1", + "extent": "40:1-40:28|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -120,9 +120,9 @@ OUTPUT: "short_name": "foo", "kind": 6, "storage": 0, - "declarations": ["65:23-65:26|15041163540773201510|2|1025"], - "spell": "79:26-79:29|15041163540773201510|2|1026", - "extent": "79:1-79:51|15041163540773201510|2|0", + "declarations": ["65:23-65:26|65:3-65:28|15041163540773201510|2|1025|-1"], + "spell": "79:26-79:29|15041163540773201510|2|1026|-1", + "extent": "79:1-79:51|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -136,8 +136,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "53:6-53:11|0|1|2", - "extent": "53:1-55:2|0|1|0", + "spell": "53:6-53:11|0|1|2|-1", + "extent": "53:1-55:2|0|1|0|-1", "bases": [], "derived": [], "vars": [500112618220246], @@ -150,7 +150,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "S1", "kind": 23, - "declarations": ["4:8-4:10|0|1|1"], + "declarations": ["4:8-4:10|4:1-4:10|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -158,29 +158,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["15:30-15:32|0|1|4", "33:23-33:25|0|1|4", "33:63-33:65|0|1|4", "54:25-54:27|18320186404467436976|3|4", "65:14-65:16|15041163540773201510|2|4", "79:12-79:14|0|1|4"] - }, { - "usr": 7147635971744144194, - "detailed_name": "template<> class unique_ptr", - "qual_name_offset": 17, - "short_name": "unique_ptr", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["15:19-15:29|0|1|4", "33:12-33:22|0|1|4", "33:52-33:62|0|1|4", "54:14-54:24|18320186404467436976|3|4", "65:3-65:13|15041163540773201510|2|4", "79:1-79:11|0|1|4"] + "uses": ["15:30-15:32|0|1|4|-1", "33:23-33:25|0|1|4|-1", "33:63-33:65|0|1|4|-1", "54:25-54:27|18320186404467436976|3|4|-1", "65:14-65:16|15041163540773201510|2|4|-1", "79:12-79:14|0|1|4|-1"] }, { "usr": 12728490517004312484, "detailed_name": "struct S2", "qual_name_offset": 7, "short_name": "S2", "kind": 23, - "declarations": ["5:8-5:10|0|1|1"], + "declarations": ["5:8-5:10|5:1-5:10|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -188,48 +173,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["15:34-15:36|0|1|4", "15:39-15:41|0|1|4", "33:27-33:29|0|1|4", "33:32-33:34|0|1|4", "33:67-33:69|0|1|4", "54:29-54:31|18320186404467436976|3|4", "54:34-54:36|18320186404467436976|3|4", "65:18-65:20|15041163540773201510|2|4", "79:16-79:18|0|1|4"] + "uses": ["15:34-15:36|0|1|4|-1", "15:39-15:41|0|1|4|-1", "33:27-33:29|0|1|4|-1", "33:32-33:34|0|1|4|-1", "33:67-33:69|0|1|4|-1", "54:29-54:31|18320186404467436976|3|4|-1", "54:34-54:36|18320186404467436976|3|4|-1", "65:18-65:20|15041163540773201510|2|4|-1", "79:16-79:18|0|1|4|-1"] }, { "usr": 14209198335088845323, "detailed_name": "class unique_ptr", "qual_name_offset": 6, "short_name": "unique_ptr", "kind": 5, - "declarations": ["2:7-2:17|0|1|1"], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": [] - }, { - "usr": 15041163540773201510, - "detailed_name": "class Foo {}", - "qual_name_offset": 6, - "short_name": "Foo", - "kind": 5, - "declarations": [], - "spell": "64:7-64:10|0|1|2", - "extent": "64:1-66:2|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [17922201480358737771], - "vars": [], - "instances": [], - "uses": ["79:21-79:24|0|1|4"] - }, { - "usr": 18153735331422331128, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, - "short_name": "unique_ptr", - "kind": 5, - "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:17|0|1|0", + "declarations": ["2:7-2:17|2:1-2:17|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -237,7 +188,24 @@ OUTPUT: "funcs": [], "vars": [], "instances": [2933643612409209903, 500112618220246], - "uses": ["15:8-15:18|0|1|4", "33:1-33:11|0|1|4", "54:3-54:13|18320186404467436976|3|4"] + "uses": ["15:8-15:18|0|1|4|-1", "15:19-15:29|0|1|4|-1", "33:1-33:11|0|1|4|-1", "33:12-33:22|0|1|4|-1", "33:52-33:62|0|1|4|-1", "54:3-54:13|18320186404467436976|3|4|-1", "54:14-54:24|18320186404467436976|3|4|-1", "65:3-65:13|15041163540773201510|2|4|-1", "79:1-79:11|0|1|4|-1"] + }, { + "usr": 15041163540773201510, + "detailed_name": "class Foo {}", + "qual_name_offset": 6, + "short_name": "Foo", + "kind": 5, + "declarations": [], + "spell": "64:7-64:10|0|1|2|-1", + "extent": "64:1-66:2|0|1|0|-1", + "alias_of": 0, + "bases": [], + "derived": [], + "types": [], + "funcs": [17922201480358737771], + "vars": [], + "instances": [], + "uses": ["79:21-79:24|0|1|4|-1"] }], "usr2var": [{ "usr": 500112618220246, @@ -245,9 +213,9 @@ OUTPUT: "qual_name_offset": 36, "short_name": "local", "declarations": [], - "spell": "54:39-54:44|18320186404467436976|3|2", - "extent": "54:3-54:44|18320186404467436976|3|0", - "type": 18153735331422331128, + "spell": "54:39-54:44|18320186404467436976|3|2|-1", + "extent": "54:3-54:44|18320186404467436976|3|0|-1", + "type": 14209198335088845323, "uses": [], "kind": 13, "storage": 0 @@ -256,8 +224,8 @@ OUTPUT: "detailed_name": "extern unique_ptr, S2> f", "qual_name_offset": 42, "short_name": "f", - "declarations": ["15:43-15:44|0|1|1"], - "type": 18153735331422331128, + "declarations": ["15:43-15:44|15:1-15:44|0|1|1|-1"], + "type": 14209198335088845323, "uses": [], "kind": 13, "storage": 1 diff --git a/index_tests/usage/type_usage_as_template_parameter_simple.cc b/index_tests/usage/type_usage_as_template_parameter_simple.cc index 1b904ef7..9f7c8da2 100644 --- a/index_tests/usage/type_usage_as_template_parameter_simple.cc +++ b/index_tests/usage/type_usage_as_template_parameter_simple.cc @@ -18,25 +18,8 @@ OUTPUT: "short_name": "unique_ptr", "kind": 5, "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "2:1-2:20|0|1|0", - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["6:8-6:18|0|1|4"] - }, { - "usr": 4186953406371619898, - "detailed_name": "unique_ptr", - "qual_name_offset": 0, - "short_name": "unique_ptr", - "kind": 26, - "declarations": [], - "spell": "2:7-2:17|0|1|2", - "extent": "1:1-2:20|0|1|0", + "spell": "2:7-2:17|0|1|2|-1", + "extent": "2:1-2:20|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -44,14 +27,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [3398408600781120939], - "uses": [] + "uses": ["6:8-6:18|0|1|4|-1"] }, { "usr": 4750332761459066907, "detailed_name": "struct S", "qual_name_offset": 7, "short_name": "S", "kind": 23, - "declarations": ["4:8-4:9|0|1|1"], + "declarations": ["4:8-4:9|4:1-4:9|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -59,7 +42,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["6:19-6:20|0|1|4"] + "uses": ["6:19-6:20|0|1|4|-1"] }], "usr2var": [{ "usr": 3398408600781120939, @@ -67,9 +50,9 @@ OUTPUT: "qual_name_offset": 21, "short_name": "foo", "declarations": [], - "spell": "6:22-6:25|0|1|2", - "extent": "6:1-6:25|0|1|0", - "type": 4186953406371619898, + "spell": "6:22-6:25|0|1|2|-1", + "extent": "6:1-6:25|0|1|0|-1", + "type": 3286534761799572592, "uses": [], "kind": 13, "storage": 2 diff --git a/index_tests/usage/type_usage_declare_extern.cc b/index_tests/usage/type_usage_declare_extern.cc index 2fd67216..4d09cd85 100644 --- a/index_tests/usage/type_usage_declare_extern.cc +++ b/index_tests/usage/type_usage_declare_extern.cc @@ -14,8 +14,8 @@ OUTPUT: "short_name": "T", "kind": 23, "declarations": [], - "spell": "1:8-1:9|0|1|2", - "extent": "1:1-1:12|0|1|0", + "spell": "1:8-1:9|0|1|2|-1", + "extent": "1:1-1:12|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -23,14 +23,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [1346710425945444872], - "uses": ["3:8-3:9|0|1|4"] + "uses": ["3:8-3:9|0|1|4|-1"] }], "usr2var": [{ "usr": 1346710425945444872, "detailed_name": "extern T t", "qual_name_offset": 9, "short_name": "t", - "declarations": ["3:10-3:11|0|1|1"], + "declarations": ["3:10-3:11|3:1-3:11|0|1|1|-1"], "type": 5673439900521455039, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_declare_field.cc b/index_tests/usage/type_usage_declare_field.cc index 114d6a86..09cae9e5 100644 --- a/index_tests/usage/type_usage_declare_field.cc +++ b/index_tests/usage/type_usage_declare_field.cc @@ -19,8 +19,8 @@ OUTPUT: "short_name": "ImplementedType", "kind": 23, "declarations": [], - "spell": "2:8-2:23|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:8-2:23|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -28,14 +28,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [14727441168849658842], - "uses": ["6:3-6:18|15041163540773201510|2|4"] + "uses": ["6:3-6:18|15041163540773201510|2|4|-1"] }, { "usr": 13749354388332789217, "detailed_name": "struct ForwardType", "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [14314859014962085433], - "uses": ["5:3-5:14|15041163540773201510|2|4"] + "uses": ["5:3-5:14|15041163540773201510|2|4|-1"] }, { "usr": 15041163540773201510, "detailed_name": "struct Foo {}", @@ -51,8 +51,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "4:8-4:11|0|1|2", - "extent": "4:1-7:2|0|1|0", + "spell": "4:8-4:11|0|1|2|-1", + "extent": "4:1-7:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -74,8 +74,8 @@ OUTPUT: "qual_name_offset": 13, "short_name": "a", "declarations": [], - "spell": "5:16-5:17|15041163540773201510|2|1026", - "extent": "5:3-5:17|15041163540773201510|2|0", + "spell": "5:16-5:17|15041163540773201510|2|1026|-1", + "extent": "5:3-5:17|15041163540773201510|2|0|-1", "type": 13749354388332789217, "uses": [], "kind": 8, @@ -86,8 +86,8 @@ OUTPUT: "qual_name_offset": 16, "short_name": "b", "declarations": [], - "spell": "6:19-6:20|15041163540773201510|2|1026", - "extent": "6:3-6:20|15041163540773201510|2|0", + "spell": "6:19-6:20|15041163540773201510|2|1026|-1", + "extent": "6:3-6:20|15041163540773201510|2|0|-1", "type": 8508299082070213750, "uses": [], "kind": 8, diff --git a/index_tests/usage/type_usage_declare_local.cc b/index_tests/usage/type_usage_declare_local.cc index 0b037bc5..39fd917d 100644 --- a/index_tests/usage/type_usage_declare_local.cc +++ b/index_tests/usage/type_usage_declare_local.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-7:2|0|1|0", + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [16374832544037266261, 2580122838476012357], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "ImplementedType", "kind": 23, "declarations": [], - "spell": "2:8-2:23|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:8-2:23|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,14 +43,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [2580122838476012357], - "uses": ["6:3-6:18|4654328188330986029|3|4"] + "uses": ["6:3-6:18|4654328188330986029|3|4|-1"] }, { "usr": 13749354388332789217, "detailed_name": "struct ForwardType", "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -58,7 +58,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [16374832544037266261], - "uses": ["5:3-5:14|4654328188330986029|3|4"] + "uses": ["5:3-5:14|4654328188330986029|3|4|-1"] }], "usr2var": [{ "usr": 2580122838476012357, @@ -66,8 +66,8 @@ OUTPUT: "qual_name_offset": 16, "short_name": "b", "declarations": [], - "spell": "6:19-6:20|4654328188330986029|3|2", - "extent": "6:3-6:20|4654328188330986029|3|0", + "spell": "6:19-6:20|4654328188330986029|3|2|-1", + "extent": "6:3-6:20|4654328188330986029|3|0|-1", "type": 8508299082070213750, "uses": [], "kind": 13, @@ -78,8 +78,8 @@ OUTPUT: "qual_name_offset": 13, "short_name": "a", "declarations": [], - "spell": "5:16-5:17|4654328188330986029|3|2", - "extent": "5:3-5:17|4654328188330986029|3|0", + "spell": "5:16-5:17|4654328188330986029|3|2|-1", + "extent": "5:3-5:17|4654328188330986029|3|0|-1", "type": 13749354388332789217, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_declare_param.cc b/index_tests/usage/type_usage_declare_param.cc index 4495b5ed..1570ef02 100644 --- a/index_tests/usage/type_usage_declare_param.cc +++ b/index_tests/usage/type_usage_declare_param.cc @@ -16,8 +16,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-4:47|0|1|0", + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-4:47|0|1|0|-1", "bases": [], "derived": [], "vars": [13058491096576226774, 11055777568039014776], @@ -31,8 +31,8 @@ OUTPUT: "short_name": "ImplementedType", "kind": 23, "declarations": [], - "spell": "2:8-2:23|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:8-2:23|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -40,14 +40,14 @@ OUTPUT: "funcs": [], "vars": [], "instances": [11055777568039014776], - "uses": ["4:26-4:41|0|1|4"] + "uses": ["4:26-4:41|0|1|4|-1"] }, { "usr": 13749354388332789217, "detailed_name": "struct ForwardType", "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -55,7 +55,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [13058491096576226774], - "uses": ["4:10-4:21|0|1|4"] + "uses": ["4:10-4:21|0|1|4|-1"] }], "usr2var": [{ "usr": 11055777568039014776, @@ -63,8 +63,8 @@ OUTPUT: "qual_name_offset": 16, "short_name": "a", "declarations": [], - "spell": "4:42-4:43|1699390678058422036|3|1026", - "extent": "4:26-4:43|1699390678058422036|3|0", + "spell": "4:42-4:43|1699390678058422036|3|1026|-1", + "extent": "4:26-4:43|1699390678058422036|3|0|-1", "type": 8508299082070213750, "uses": [], "kind": 253, @@ -75,8 +75,8 @@ OUTPUT: "qual_name_offset": 13, "short_name": "f", "declarations": [], - "spell": "4:23-4:24|1699390678058422036|3|1026", - "extent": "4:10-4:24|1699390678058422036|3|0", + "spell": "4:23-4:24|1699390678058422036|3|1026|-1", + "extent": "4:10-4:24|1699390678058422036|3|0|-1", "type": 13749354388332789217, "uses": [], "kind": 253, diff --git a/index_tests/usage/type_usage_declare_param_prototype.cc b/index_tests/usage/type_usage_declare_param_prototype.cc index cee27557..3f205c9d 100644 --- a/index_tests/usage/type_usage_declare_param_prototype.cc +++ b/index_tests/usage/type_usage_declare_param_prototype.cc @@ -20,9 +20,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["3:6-3:9|0|1|1"], - "spell": "4:6-4:9|0|1|2", - "extent": "4:1-4:26|0|1|0", + "declarations": ["3:6-3:9|3:1-3:23|0|1|1|-1"], + "spell": "4:6-4:9|0|1|2|-1", + "extent": "4:1-4:26|0|1|0|-1", "bases": [], "derived": [], "vars": [13823260660189154978], @@ -35,7 +35,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [13823260660189154978], - "uses": ["3:10-3:13|0|1|4", "3:18-3:21|0|1|4", "4:10-4:13|0|1|4", "4:18-4:21|0|1|4"] + "uses": ["3:10-3:13|0|1|4|-1", "3:18-3:21|0|1|4|-1", "4:10-4:13|0|1|4|-1", "4:18-4:21|0|1|4|-1"] }], "usr2var": [{ "usr": 13823260660189154978, @@ -51,8 +51,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "f", "declarations": [], - "spell": "4:15-4:16|8908726657907936744|3|1026", - "extent": "4:10-4:16|8908726657907936744|3|0", + "spell": "4:15-4:16|8908726657907936744|3|1026|-1", + "extent": "4:10-4:16|8908726657907936744|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 253, diff --git a/index_tests/usage/type_usage_declare_param_unnamed.cc b/index_tests/usage/type_usage_declare_param_unnamed.cc index f0cda536..f50fab00 100644 --- a/index_tests/usage/type_usage_declare_param_unnamed.cc +++ b/index_tests/usage/type_usage_declare_param_unnamed.cc @@ -13,8 +13,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:9|0|1|2", - "extent": "2:1-2:26|0|1|0", + "spell": "2:6-2:9|0|1|2|-1", + "extent": "2:1-2:26|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -27,7 +27,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "ForwardType", "kind": 23, - "declarations": ["1:8-1:19|0|1|1"], + "declarations": ["1:8-1:19|1:1-1:19|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -35,7 +35,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:10-2:21|0|1|4"] + "uses": ["2:10-2:21|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/type_usage_declare_qualifiers.cc b/index_tests/usage/type_usage_declare_qualifiers.cc index 41dfc325..ec1f4d9c 100644 --- a/index_tests/usage/type_usage_declare_qualifiers.cc +++ b/index_tests/usage/type_usage_declare_qualifiers.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-8:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [7997456978847868736, 17228576662112939520, 15429032129697337561, 6081981442495435784, 5004072032239834773, 14939253431683105646], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "Type", "kind": 23, "declarations": [], - "spell": "1:8-1:12|0|1|2", - "extent": "1:1-1:15|0|1|0", + "spell": "1:8-1:12|0|1|2|-1", + "extent": "1:1-1:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [7997456978847868736, 17228576662112939520, 15429032129697337561, 6081981442495435784, 5004072032239834773, 14939253431683105646], - "uses": ["3:10-3:14|0|1|4", "3:26-3:30|0|1|4", "4:3-4:7|16858540520096802573|3|4", "5:3-5:7|16858540520096802573|3|4", "6:9-6:13|16858540520096802573|3|4", "7:9-7:13|16858540520096802573|3|4"] + "uses": ["3:10-3:14|0|1|4|-1", "3:26-3:30|0|1|4|-1", "4:3-4:7|16858540520096802573|3|4|-1", "5:3-5:7|16858540520096802573|3|4|-1", "6:9-6:13|16858540520096802573|3|4|-1", "7:9-7:13|16858540520096802573|3|4|-1"] }], "usr2var": [{ "usr": 5004072032239834773, @@ -51,8 +51,8 @@ OUTPUT: "qual_name_offset": 12, "short_name": "a4", "declarations": [], - "spell": "6:15-6:17|16858540520096802573|3|2", - "extent": "6:3-6:17|16858540520096802573|3|0", + "spell": "6:15-6:17|16858540520096802573|3|2|-1", + "extent": "6:3-6:17|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -63,8 +63,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "a3", "declarations": [], - "spell": "5:9-5:11|16858540520096802573|3|2", - "extent": "5:3-5:11|16858540520096802573|3|0", + "spell": "5:9-5:11|16858540520096802573|3|2|-1", + "extent": "5:3-5:11|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -75,8 +75,8 @@ OUTPUT: "qual_name_offset": 6, "short_name": "a0", "declarations": [], - "spell": "3:16-3:18|16858540520096802573|3|1026", - "extent": "3:10-3:18|16858540520096802573|3|0", + "spell": "3:16-3:18|16858540520096802573|3|1026|-1", + "extent": "3:10-3:18|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 253, @@ -88,8 +88,8 @@ OUTPUT: "short_name": "a5", "hover": "const Type *const a5 = nullptr", "declarations": [], - "spell": "7:21-7:23|16858540520096802573|3|2", - "extent": "7:3-7:33|16858540520096802573|3|0", + "spell": "7:21-7:23|16858540520096802573|3|2|-1", + "extent": "7:3-7:33|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -100,8 +100,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "a2", "declarations": [], - "spell": "4:8-4:10|16858540520096802573|3|2", - "extent": "4:3-4:10|16858540520096802573|3|0", + "spell": "4:8-4:10|16858540520096802573|3|2|-1", + "extent": "4:3-4:10|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, @@ -112,8 +112,8 @@ OUTPUT: "qual_name_offset": 12, "short_name": "a1", "declarations": [], - "spell": "3:32-3:34|16858540520096802573|3|1026", - "extent": "3:20-3:34|16858540520096802573|3|0", + "spell": "3:32-3:34|16858540520096802573|3|1026|-1", + "extent": "3:20-3:34|16858540520096802573|3|0|-1", "type": 13487927231218873822, "uses": [], "kind": 253, diff --git a/index_tests/usage/type_usage_declare_static.cc b/index_tests/usage/type_usage_declare_static.cc index 102c156a..ccff19e2 100644 --- a/index_tests/usage/type_usage_declare_static.cc +++ b/index_tests/usage/type_usage_declare_static.cc @@ -13,8 +13,8 @@ OUTPUT: "short_name": "Type", "kind": 23, "declarations": [], - "spell": "1:8-1:12|0|1|2", - "extent": "1:1-1:15|0|1|0", + "spell": "1:8-1:12|0|1|2|-1", + "extent": "1:1-1:15|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -22,7 +22,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [6601831367240627080], - "uses": ["2:8-2:12|0|1|4"] + "uses": ["2:8-2:12|0|1|4|-1"] }], "usr2var": [{ "usr": 6601831367240627080, @@ -30,8 +30,8 @@ OUTPUT: "qual_name_offset": 12, "short_name": "t", "declarations": [], - "spell": "2:13-2:14|0|1|2", - "extent": "2:1-2:14|0|1|0", + "spell": "2:13-2:14|0|1|2|-1", + "extent": "2:1-2:14|0|1|0|-1", "type": 13487927231218873822, "uses": [], "kind": 13, diff --git a/index_tests/usage/type_usage_on_return_type.cc b/index_tests/usage/type_usage_on_return_type.cc index 04e84860..7a07f973 100644 --- a/index_tests/usage/type_usage_on_return_type.cc +++ b/index_tests/usage/type_usage_on_return_type.cc @@ -29,9 +29,9 @@ OUTPUT: "short_name": "Empty", "kind": 6, "storage": 0, - "declarations": ["9:8-9:13|15041163540773201510|2|1025"], - "spell": "13:11-13:16|15041163540773201510|2|1026", - "extent": "13:1-13:21|15041163540773201510|2|0", + "declarations": ["9:8-9:13|9:3-9:15|15041163540773201510|2|1025|-1"], + "spell": "13:11-13:16|15041163540773201510|2|1026|-1", + "extent": "13:1-13:21|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -44,9 +44,9 @@ OUTPUT: "short_name": "foo", "kind": 12, "storage": 0, - "declarations": ["3:7-3:10|0|1|1", "4:7-4:10|0|1|1"], - "spell": "5:7-5:10|0|1|2", - "extent": "5:1-5:32|0|1|0", + "declarations": ["3:7-3:10|3:1-3:12|0|1|1|-1", "4:7-4:10|4:1-4:12|0|1|1|-1"], + "spell": "5:7-5:10|0|1|2|-1", + "extent": "5:1-5:32|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -59,7 +59,7 @@ OUTPUT: "short_name": "external", "kind": 12, "storage": 0, - "declarations": ["15:20-15:28|0|1|1"], + "declarations": ["15:20-15:28|15:1-15:30|0|1|1|-1"], "bases": [], "derived": [], "vars": [], @@ -72,9 +72,9 @@ OUTPUT: "short_name": "Get", "kind": 6, "storage": 0, - "declarations": ["8:9-8:12|15041163540773201510|2|1025"], - "spell": "12:12-12:15|15041163540773201510|2|1026", - "extent": "12:1-12:40|15041163540773201510|2|0", + "declarations": ["8:9-8:12|8:3-8:17|15041163540773201510|2|1025|-1"], + "spell": "12:12-12:15|15041163540773201510|2|1026|-1", + "extent": "12:1-12:40|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [], @@ -87,9 +87,9 @@ OUTPUT: "short_name": "bar", "kind": 12, "storage": 0, - "declarations": ["17:14-17:17|0|1|1"], - "spell": "18:14-18:17|0|1|2", - "extent": "18:1-18:39|0|1|0", + "declarations": ["17:14-17:17|17:1-17:19|0|1|1|-1"], + "spell": "18:14-18:17|0|1|2|-1", + "extent": "18:1-18:39|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -102,7 +102,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Type", "kind": 23, - "declarations": ["1:8-1:12|0|1|1"], + "declarations": ["1:8-1:12|1:1-1:12|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -110,7 +110,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["3:1-3:5|0|1|4", "4:1-4:5|0|1|4", "5:1-5:5|0|1|4", "8:3-8:7|15041163540773201510|2|4", "12:1-12:5|0|1|4", "15:14-15:18|0|1|4", "17:8-17:12|0|1|4", "18:8-18:12|0|1|4"] + "uses": ["3:1-3:5|0|1|4|-1", "4:1-4:5|0|1|4|-1", "5:1-5:5|0|1|4|-1", "8:3-8:7|15041163540773201510|2|4|-1", "12:1-12:5|0|1|4|-1", "15:14-15:18|0|1|4|-1", "17:8-17:12|0|1|4|-1", "18:8-18:12|0|1|4|-1"] }, { "usr": 15041163540773201510, "detailed_name": "class Foo {}", @@ -118,8 +118,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "7:7-7:10|0|1|2", - "extent": "7:1-10:2|0|1|0", + "spell": "7:7-7:10|0|1|2|-1", + "extent": "7:1-10:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -127,7 +127,7 @@ OUTPUT: "funcs": [13402221340333431092, 4240751906910175539], "vars": [], "instances": [], - "uses": ["12:7-12:10|0|1|4", "13:6-13:9|0|1|4"] + "uses": ["12:7-12:10|0|1|4|-1", "13:6-13:9|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/type_usage_typedef_and_using.cc b/index_tests/usage/type_usage_typedef_and_using.cc index ded74f43..65ca72f3 100644 --- a/index_tests/usage/type_usage_typedef_and_using.cc +++ b/index_tests/usage/type_usage_typedef_and_using.cc @@ -22,8 +22,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "8:6-8:13|0|1|2", - "extent": "8:1-8:23|0|1|0", + "spell": "8:6-8:13|0|1|2|-1", + "extent": "8:1-8:23|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -37,8 +37,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:6-7:12|0|1|2", - "extent": "7:1-7:21|0|1|0", + "spell": "7:6-7:12|0|1|2|-1", + "extent": "7:1-7:21|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -52,8 +52,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "9:6-9:13|0|1|2", - "extent": "9:1-9:23|0|1|0", + "spell": "9:6-9:13|0|1|2|-1", + "extent": "9:1-9:23|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -67,8 +67,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "10:6-10:13|0|1|2", - "extent": "10:1-10:23|0|1|0", + "spell": "10:6-10:13|0|1|2|-1", + "extent": "10:1-10:23|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -82,8 +82,8 @@ OUTPUT: "short_name": "Foo1", "kind": 252, "declarations": [], - "spell": "2:7-2:11|0|1|2", - "extent": "2:1-2:18|0|1|0", + "spell": "2:7-2:11|0|1|2|-1", + "extent": "2:1-2:18|0|1|0|-1", "alias_of": 15041163540773201510, "bases": [], "derived": [], @@ -91,7 +91,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["4:14-4:18|0|1|4", "8:14-8:18|0|1|4"] + "uses": ["4:14-4:18|0|1|4|-1", "8:14-8:18|0|1|4|-1"] }, { "usr": 2638219001294786365, "detailed_name": "using Foo4 = int", @@ -99,8 +99,8 @@ OUTPUT: "short_name": "Foo4", "kind": 252, "declarations": [], - "spell": "5:7-5:11|0|1|2", - "extent": "5:1-5:17|0|1|0", + "spell": "5:7-5:11|0|1|2|-1", + "extent": "5:1-5:17|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -115,7 +115,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -123,7 +123,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:14-2:17|0|1|4", "3:9-3:12|0|1|4", "7:13-7:16|0|1|4"] + "uses": ["2:14-2:17|0|1|4|-1", "3:9-3:12|0|1|4|-1", "7:13-7:16|0|1|4|-1"] }, { "usr": 15466821155413653804, "detailed_name": "typedef Foo Foo2", @@ -131,8 +131,8 @@ OUTPUT: "short_name": "Foo2", "kind": 252, "declarations": [], - "spell": "3:13-3:17|0|1|2", - "extent": "3:1-3:17|0|1|0", + "spell": "3:13-3:17|0|1|2|-1", + "extent": "3:1-3:17|0|1|0|-1", "alias_of": 15041163540773201510, "bases": [], "derived": [], @@ -140,7 +140,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["9:14-9:18|0|1|4"] + "uses": ["9:14-9:18|0|1|4|-1"] }, { "usr": 17897026942631673064, "detailed_name": "using Foo3 = Foo1", @@ -148,8 +148,8 @@ OUTPUT: "short_name": "Foo3", "kind": 252, "declarations": [], - "spell": "4:7-4:11|0|1|2", - "extent": "4:1-4:18|0|1|0", + "spell": "4:7-4:11|0|1|2|-1", + "extent": "4:1-4:18|0|1|0|-1", "alias_of": 1544499294580512394, "bases": [], "derived": [], @@ -157,7 +157,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["10:14-10:18|0|1|4"] + "uses": ["10:14-10:18|0|1|4|-1"] }], "usr2var": [] } diff --git a/index_tests/usage/type_usage_typedef_and_using_template.cc b/index_tests/usage/type_usage_typedef_and_using_template.cc index c9328477..3c742067 100644 --- a/index_tests/usage/type_usage_typedef_and_using_template.cc +++ b/index_tests/usage/type_usage_typedef_and_using_template.cc @@ -17,53 +17,23 @@ OUTPUT: "short_name": "Foo1", "kind": 252, "declarations": [], - "spell": "4:7-4:11|0|1|2", - "extent": "4:1-4:22|0|1|0", - "alias_of": 5123806965838456033, + "spell": "4:7-4:11|0|1|2|-1", + "extent": "4:1-4:22|0|1|0|-1", + "alias_of": 10528472276654770367, "bases": [], "derived": [], "types": [], "funcs": [], "vars": [], "instances": [], - "uses": ["5:13-5:17|0|1|4"] - }, { - "usr": 5123806965838456033, - "detailed_name": "template<> struct Foo", - "qual_name_offset": 18, - "short_name": "Foo", - "kind": 5, - "declarations": [], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": ["4:14-4:17|0|1|4"] + "uses": ["5:13-5:17|0|1|4|-1"] }, { "usr": 10528472276654770367, "detailed_name": "struct Foo", "qual_name_offset": 7, "short_name": "Foo", - "kind": 23, - "declarations": ["2:8-2:11|0|1|1"], - "alias_of": 0, - "bases": [], - "derived": [], - "types": [], - "funcs": [], - "vars": [], - "instances": [], - "uses": [] - }, { - "usr": 14491685842684954828, - "detailed_name": "template<> struct Foo>", - "qual_name_offset": 18, - "short_name": "Foo", "kind": 5, - "declarations": [], + "declarations": ["2:8-2:11|2:1-2:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -71,7 +41,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["5:9-5:12|0|1|4"] + "uses": ["4:14-4:17|0|1|4|-1", "5:9-5:12|0|1|4|-1"] }, { "usr": 15933698173231330933, "detailed_name": "typedef Foo Foo2", @@ -79,9 +49,9 @@ OUTPUT: "short_name": "Foo2", "kind": 252, "declarations": [], - "spell": "5:19-5:23|0|1|2", - "extent": "5:1-5:23|0|1|0", - "alias_of": 14491685842684954828, + "spell": "5:19-5:23|0|1|2|-1", + "extent": "5:1-5:23|0|1|0|-1", + "alias_of": 10528472276654770367, "bases": [], "derived": [], "types": [], diff --git a/index_tests/usage/type_usage_various.cc b/index_tests/usage/type_usage_various.cc index fead6f19..5baaf0f8 100644 --- a/index_tests/usage/type_usage_various.cc +++ b/index_tests/usage/type_usage_various.cc @@ -21,9 +21,9 @@ OUTPUT: "short_name": "make", "kind": 6, "storage": 0, - "declarations": ["2:8-2:12|15041163540773201510|2|1025"], - "spell": "5:11-5:15|15041163540773201510|2|1026", - "extent": "5:1-8:2|15041163540773201510|2|0", + "declarations": ["2:8-2:12|2:3-2:14|15041163540773201510|2|1025|-1"], + "spell": "5:11-5:15|15041163540773201510|2|1026|-1", + "extent": "5:1-8:2|15041163540773201510|2|0|-1", "bases": [], "derived": [], "vars": [16380484338511689669], @@ -37,8 +37,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -46,14 +46,14 @@ OUTPUT: "funcs": [9488177941273031343], "vars": [], "instances": [16380484338511689669, 14455976355866885943], - "uses": ["2:3-2:6|15041163540773201510|2|4", "5:1-5:4|0|1|4", "5:6-5:9|0|1|4", "6:3-6:6|9488177941273031343|3|4", "10:8-10:11|0|1|4"] + "uses": ["2:3-2:6|15041163540773201510|2|4|-1", "5:1-5:4|0|1|4|-1", "5:6-5:9|0|1|4|-1", "6:3-6:6|9488177941273031343|3|4|-1", "10:8-10:11|0|1|4|-1"] }], "usr2var": [{ "usr": 14455976355866885943, "detailed_name": "extern Foo foo", "qual_name_offset": 11, "short_name": "foo", - "declarations": ["10:12-10:15|0|1|1"], + "declarations": ["10:12-10:15|10:1-10:15|0|1|1|-1"], "type": 15041163540773201510, "uses": [], "kind": 13, @@ -64,8 +64,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "6:7-6:8|9488177941273031343|3|2", - "extent": "6:3-6:8|9488177941273031343|3|0", + "spell": "6:7-6:8|9488177941273031343|3|2|-1", + "extent": "6:3-6:8|9488177941273031343|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/usage/usage_inside_of_call.cc b/index_tests/usage/usage_inside_of_call.cc index 036671a4..39ef7456 100644 --- a/index_tests/usage/usage_inside_of_call.cc +++ b/index_tests/usage/usage_inside_of_call.cc @@ -27,8 +27,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "12:6-12:9|0|1|2", - "extent": "12:1-15:2|0|1|0", + "spell": "12:6-12:9|0|1|2|-1", + "extent": "12:1-15:2|0|1|0|-1", "bases": [], "derived": [], "vars": [8039186520399841081], @@ -41,11 +41,11 @@ OUTPUT: "short_name": "gen", "kind": 12, "storage": 0, - "declarations": ["3:5-3:8|0|1|1"], + "declarations": ["3:5-3:8|3:1-3:10|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["14:14-14:17|4259594751088586730|3|16420"], + "uses": ["14:14-14:17|4259594751088586730|3|16420|-1"], "callees": [] }, { "usr": 18319417758892371313, @@ -54,11 +54,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["1:6-1:12|0|1|1"], + "declarations": ["1:6-1:12|1:1-1:19|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["14:3-14:9|4259594751088586730|3|16420"], + "uses": ["14:3-14:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -83,8 +83,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "5:8-5:11|0|1|2", - "extent": "5:1-8:2|0|1|0", + "spell": "5:8-5:11|0|1|2|-1", + "extent": "5:1-8:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -95,7 +95,7 @@ OUTPUT: "R": 0 }], "instances": [], - "uses": ["10:5-10:8|0|1|4", "14:22-14:25|4259594751088586730|3|4", "14:40-14:43|4259594751088586730|3|4"] + "uses": ["10:5-10:8|0|1|4|-1", "14:22-14:25|4259594751088586730|3|4|-1", "14:40-14:43|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 8039186520399841081, @@ -104,10 +104,10 @@ OUTPUT: "short_name": "a", "hover": "int a = 5", "declarations": [], - "spell": "13:7-13:8|4259594751088586730|3|2", - "extent": "13:3-13:12|4259594751088586730|3|0", + "spell": "13:7-13:8|4259594751088586730|3|2|-1", + "extent": "13:3-13:12|4259594751088586730|3|0|-1", "type": 53, - "uses": ["14:10-14:11|4259594751088586730|3|12"], + "uses": ["14:10-14:11|4259594751088586730|3|12|-1"], "kind": 13, "storage": 0 }, { @@ -116,10 +116,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "field_var", "declarations": [], - "spell": "7:7-7:16|15041163540773201510|2|1026", - "extent": "7:3-7:16|15041163540773201510|2|0", + "spell": "7:7-7:16|15041163540773201510|2|1026|-1", + "extent": "7:3-7:16|15041163540773201510|2|0|-1", "type": 53, - "uses": ["14:28-14:37|4259594751088586730|3|12"], + "uses": ["14:28-14:37|4259594751088586730|3|12|-1"], "kind": 8, "storage": 0 }, { @@ -127,11 +127,11 @@ OUTPUT: "detailed_name": "static int Foo::static_var", "qual_name_offset": 11, "short_name": "static_var", - "declarations": ["6:14-6:24|15041163540773201510|2|1025"], - "spell": "10:10-10:20|15041163540773201510|2|1026", - "extent": "10:1-10:24|15041163540773201510|2|0", + "declarations": ["6:14-6:24|6:3-6:24|15041163540773201510|2|1025|-1"], + "spell": "10:10-10:20|15041163540773201510|2|1026|-1", + "extent": "10:1-10:24|15041163540773201510|2|0|-1", "type": 53, - "uses": ["14:45-14:55|4259594751088586730|3|12"], + "uses": ["14:45-14:55|4259594751088586730|3|12|-1"], "kind": 13, "storage": 2 }] diff --git a/index_tests/usage/usage_inside_of_call_simple.cc b/index_tests/usage/usage_inside_of_call_simple.cc index 9bb67ba9..db2c738e 100644 --- a/index_tests/usage/usage_inside_of_call_simple.cc +++ b/index_tests/usage/usage_inside_of_call_simple.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "5:6-5:9|0|1|2", - "extent": "5:1-7:2|0|1|0", + "spell": "5:6-5:9|0|1|2|-1", + "extent": "5:1-7:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -34,12 +34,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:5-3:8|0|1|2", - "extent": "3:1-3:24|0|1|0", + "spell": "3:5-3:8|0|1|2|-1", + "extent": "3:1-3:24|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["6:10-6:13|4259594751088586730|3|16420", "6:18-6:21|4259594751088586730|3|16420"], + "uses": ["6:10-6:13|4259594751088586730|3|16420|-1", "6:18-6:21|4259594751088586730|3|16420|-1"], "callees": [] }, { "usr": 18319417758892371313, @@ -48,11 +48,11 @@ OUTPUT: "short_name": "called", "kind": 12, "storage": 0, - "declarations": ["1:6-1:12|0|1|1"], + "declarations": ["1:6-1:12|1:1-1:19|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["6:3-6:9|4259594751088586730|3|16420"], + "uses": ["6:3-6:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [], diff --git a/index_tests/usage/var_usage_call_function.cc b/index_tests/usage/var_usage_call_function.cc index 5ac9d0fa..e28d0954 100644 --- a/index_tests/usage/var_usage_call_function.cc +++ b/index_tests/usage/var_usage_call_function.cc @@ -20,12 +20,12 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:12|0|1|2", - "extent": "1:1-1:17|0|1|0", + "spell": "1:6-1:12|0|1|2|-1", + "extent": "1:1-1:17|0|1|0|-1", "bases": [], "derived": [], "vars": [], - "uses": ["4:13-4:19|11404881820527069090|3|132", "7:3-7:9|11404881820527069090|3|16420"], + "uses": ["4:13-4:19|11404881820527069090|3|132|-1", "7:3-7:9|11404881820527069090|3|16420|-1"], "callees": [] }, { "usr": 11404881820527069090, @@ -35,8 +35,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:12|0|1|2", - "extent": "3:1-8:2|0|1|0", + "spell": "3:6-3:12|0|1|2|-1", + "extent": "3:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [9121974011454213596], @@ -51,10 +51,10 @@ OUTPUT: "short_name": "x", "hover": "auto x = &called", "declarations": [], - "spell": "4:8-4:9|11404881820527069090|3|2", - "extent": "4:3-4:19|11404881820527069090|3|0", + "spell": "4:8-4:9|11404881820527069090|3|2|-1", + "extent": "4:3-4:19|11404881820527069090|3|0|-1", "type": 0, - "uses": ["5:3-5:4|11404881820527069090|3|16428"], + "uses": ["5:3-5:4|11404881820527069090|3|16428|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_class_member.cc b/index_tests/usage/var_usage_class_member.cc index 93667b6d..1a25fe9f 100644 --- a/index_tests/usage/var_usage_class_member.cc +++ b/index_tests/usage/var_usage_class_member.cc @@ -30,8 +30,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "10:6-10:9|0|1|2", - "extent": "10:1-18:2|0|1|0", + "spell": "10:6-10:9|0|1|2|-1", + "extent": "10:1-18:2|0|1|0|-1", "bases": [], "derived": [], "vars": [14669930844300034456], @@ -44,11 +44,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["8:6-8:12|0|1|1"], + "declarations": ["8:6-8:12|8:1-8:18|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["16:3-16:9|4259594751088586730|3|16420"], + "uses": ["16:3-16:9|4259594751088586730|3|16420|-1"], "callees": [] }, { "usr": 17175780305784503374, @@ -57,11 +57,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["7:6-7:12|0|1|1"], + "declarations": ["7:6-7:12|7:1-7:17|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["14:3-14:9|4259594751088586730|3|16420", "15:3-15:9|4259594751088586730|3|16420", "17:3-17:9|4259594751088586730|3|16420"], + "uses": ["14:3-14:9|4259594751088586730|3|16420|-1", "15:3-15:9|4259594751088586730|3|16420|-1", "17:3-17:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -86,8 +86,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-5:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -101,7 +101,7 @@ OUTPUT: "R": 32 }], "instances": [14669930844300034456], - "uses": ["11:3-11:6|4259594751088586730|3|4"] + "uses": ["11:3-11:6|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 3873837747174060388, @@ -109,10 +109,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "y", "declarations": [], - "spell": "4:7-4:8|15041163540773201510|2|1026", - "extent": "4:3-4:8|15041163540773201510|2|0", + "spell": "4:7-4:8|15041163540773201510|2|1026|-1", + "extent": "4:3-4:8|15041163540773201510|2|0|-1", "type": 53, - "uses": ["17:12-17:13|4259594751088586730|3|12"], + "uses": ["17:12-17:13|4259594751088586730|3|12|-1"], "kind": 8, "storage": 0 }, { @@ -121,10 +121,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "x", "declarations": [], - "spell": "3:7-3:8|15041163540773201510|2|1026", - "extent": "3:3-3:8|15041163540773201510|2|0", + "spell": "3:7-3:8|15041163540773201510|2|1026|-1", + "extent": "3:3-3:8|15041163540773201510|2|0|-1", "type": 53, - "uses": ["12:5-12:6|4259594751088586730|3|20", "13:5-13:6|4259594751088586730|3|4", "14:12-14:13|4259594751088586730|3|12", "15:12-15:13|4259594751088586730|3|12", "16:13-16:14|4259594751088586730|3|132"], + "uses": ["12:5-12:6|4259594751088586730|3|20|-1", "13:5-13:6|4259594751088586730|3|4|-1", "14:12-14:13|4259594751088586730|3|12|-1", "15:12-15:13|4259594751088586730|3|12|-1", "16:13-16:14|4259594751088586730|3|132|-1"], "kind": 8, "storage": 0 }, { @@ -133,10 +133,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "f", "declarations": [], - "spell": "11:7-11:8|4259594751088586730|3|2", - "extent": "11:3-11:8|4259594751088586730|3|0", + "spell": "11:7-11:8|4259594751088586730|3|2|-1", + "extent": "11:3-11:8|4259594751088586730|3|0|-1", "type": 15041163540773201510, - "uses": ["12:3-12:4|4259594751088586730|3|4", "13:3-13:4|4259594751088586730|3|4", "14:10-14:11|4259594751088586730|3|4", "15:10-15:11|4259594751088586730|3|4", "16:11-16:12|4259594751088586730|3|4", "17:10-17:11|4259594751088586730|3|4"], + "uses": ["12:3-12:4|4259594751088586730|3|4|-1", "13:3-13:4|4259594751088586730|3|4|-1", "14:10-14:11|4259594751088586730|3|4|-1", "15:10-15:11|4259594751088586730|3|4|-1", "16:11-16:12|4259594751088586730|3|4|-1", "17:10-17:11|4259594751088586730|3|4|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_class_member_static.cc b/index_tests/usage/var_usage_class_member_static.cc index 6f2eee7d..8c21456f 100644 --- a/index_tests/usage/var_usage_class_member_static.cc +++ b/index_tests/usage/var_usage_class_member_static.cc @@ -21,8 +21,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "7:6-7:9|0|1|2", - "extent": "7:1-9:2|0|1|0", + "spell": "7:6-7:9|0|1|2|-1", + "extent": "7:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -35,11 +35,11 @@ OUTPUT: "short_name": "accept", "kind": 12, "storage": 0, - "declarations": ["5:6-5:12|0|1|1"], + "declarations": ["5:6-5:12|5:1-5:17|0|1|1|-1"], "bases": [], "derived": [], "vars": [], - "uses": ["8:3-8:9|4259594751088586730|3|16420"], + "uses": ["8:3-8:9|4259594751088586730|3|16420|-1"], "callees": [] }], "usr2type": [{ @@ -64,8 +64,8 @@ OUTPUT: "short_name": "Foo", "kind": 23, "declarations": [], - "spell": "1:8-1:11|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:8-1:11|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -73,16 +73,16 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["8:10-8:13|4259594751088586730|3|4"] + "uses": ["8:10-8:13|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 8599782646965457351, "detailed_name": "static int Foo::x", "qual_name_offset": 11, "short_name": "x", - "declarations": ["2:14-2:15|15041163540773201510|2|1025"], + "declarations": ["2:14-2:15|2:3-2:15|15041163540773201510|2|1025|-1"], "type": 53, - "uses": ["8:15-8:16|4259594751088586730|3|12"], + "uses": ["8:15-8:16|4259594751088586730|3|12|-1"], "kind": 13, "storage": 2 }] diff --git a/index_tests/usage/var_usage_cstyle_cast.cc b/index_tests/usage/var_usage_cstyle_cast.cc index 1233becc..dd3fe708 100644 --- a/index_tests/usage/var_usage_cstyle_cast.cc +++ b/index_tests/usage/var_usage_cstyle_cast.cc @@ -15,13 +15,13 @@ OUTPUT: "usr2func": [], "usr2type": [{ "usr": 5792006888140599735, - "detailed_name": "enum VarType {\n}", + "detailed_name": "enum VarType {}", "qual_name_offset": 5, "short_name": "VarType", "kind": 10, "declarations": [], - "spell": "1:6-1:13|0|1|2", - "extent": "1:1-1:16|0|1|0", + "spell": "1:6-1:13|0|1|2|-1", + "extent": "1:1-1:16|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -29,7 +29,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [7057400933868440116, 7057400933868440116], - "uses": ["4:20-4:27|10028537921178202800|2|4", "4:42-4:49|10028537921178202800|2|4", "7:7-7:14|0|1|4"] + "uses": ["4:20-4:27|10028537921178202800|2|4|-1", "4:42-4:49|10028537921178202800|2|4|-1", "7:7-7:14|0|1|4|-1"] }, { "usr": 10028537921178202800, "detailed_name": "struct Holder {}", @@ -37,8 +37,8 @@ OUTPUT: "short_name": "Holder", "kind": 23, "declarations": [], - "spell": "3:8-3:14|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:8-3:14|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -46,7 +46,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["7:15-7:21|0|1|4"] + "uses": ["7:15-7:21|0|1|4|-1"] }], "usr2var": [{ "usr": 7057400933868440116, @@ -54,9 +54,9 @@ OUTPUT: "qual_name_offset": 25, "short_name": "static_var", "hover": "static constexpr VarType Holder::static_var = (VarType)0x0", - "declarations": ["4:28-4:38|10028537921178202800|2|1025"], - "spell": "7:23-7:33|10028537921178202800|2|1026", - "extent": "7:1-7:33|10028537921178202800|2|0", + "declarations": ["4:28-4:38|4:3-4:53|10028537921178202800|2|1025|-1"], + "spell": "7:23-7:33|10028537921178202800|2|1026|-1", + "extent": "7:1-7:33|10028537921178202800|2|0|-1", "type": 5792006888140599735, "uses": [], "kind": 13, diff --git a/index_tests/usage/var_usage_extern.cc b/index_tests/usage/var_usage_extern.cc index 09442598..0d3469e6 100644 --- a/index_tests/usage/var_usage_extern.cc +++ b/index_tests/usage/var_usage_extern.cc @@ -16,8 +16,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -45,9 +45,9 @@ OUTPUT: "detailed_name": "extern int a", "qual_name_offset": 11, "short_name": "a", - "declarations": ["1:12-1:13|0|1|1"], + "declarations": ["1:12-1:13|1:1-1:13|0|1|1|-1"], "type": 53, - "uses": ["4:3-4:4|4259594751088586730|3|20"], + "uses": ["4:3-4:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 1 }] diff --git a/index_tests/usage/var_usage_func_parameter.cc b/index_tests/usage/var_usage_func_parameter.cc index 9bfd50aa..2a5e0867 100644 --- a/index_tests/usage/var_usage_func_parameter.cc +++ b/index_tests/usage/var_usage_func_parameter.cc @@ -14,8 +14,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "bases": [], "derived": [], "vars": [10063793875496522529], @@ -44,10 +44,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "1:14-1:15|11998306017310352355|3|1026", - "extent": "1:10-1:15|11998306017310352355|3|0", + "spell": "1:14-1:15|11998306017310352355|3|1026|-1", + "extent": "1:10-1:15|11998306017310352355|3|0|-1", "type": 53, - "uses": ["2:3-2:4|11998306017310352355|3|4"], + "uses": ["2:3-2:4|11998306017310352355|3|4|-1"], "kind": 253, "storage": 0 }] diff --git a/index_tests/usage/var_usage_local.cc b/index_tests/usage/var_usage_local.cc index f6eb9d02..b4ed3842 100644 --- a/index_tests/usage/var_usage_local.cc +++ b/index_tests/usage/var_usage_local.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-4:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-4:2|0|1|0|-1", "bases": [], "derived": [], "vars": [14014650769929566957], @@ -45,10 +45,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "x", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["3:3-3:4|4259594751088586730|3|20"], + "uses": ["3:3-3:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_shadowed_local.cc b/index_tests/usage/var_usage_shadowed_local.cc index d0f9a35f..2aaf27be 100644 --- a/index_tests/usage/var_usage_shadowed_local.cc +++ b/index_tests/usage/var_usage_shadowed_local.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-9:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [13311055950748663970, 14036425367303419504], @@ -50,10 +50,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["3:3-3:4|4259594751088586730|3|20", "8:3-8:4|4259594751088586730|3|20"], + "uses": ["3:3-3:4|4259594751088586730|3|20|-1", "8:3-8:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }, { @@ -62,10 +62,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "5:9-5:10|4259594751088586730|3|2", - "extent": "5:5-5:10|4259594751088586730|3|0", + "spell": "5:9-5:10|4259594751088586730|3|2|-1", + "extent": "5:5-5:10|4259594751088586730|3|0|-1", "type": 53, - "uses": ["6:5-6:6|4259594751088586730|3|20"], + "uses": ["6:5-6:6|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/usage/var_usage_shadowed_parameter.cc b/index_tests/usage/var_usage_shadowed_parameter.cc index 8a99171d..801f3a75 100644 --- a/index_tests/usage/var_usage_shadowed_parameter.cc +++ b/index_tests/usage/var_usage_shadowed_parameter.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-8:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-8:2|0|1|0|-1", "bases": [], "derived": [], "vars": [11608231465452906059, 6997229590862003559], @@ -50,10 +50,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "4:9-4:10|11998306017310352355|3|2", - "extent": "4:5-4:10|11998306017310352355|3|0", + "spell": "4:9-4:10|11998306017310352355|3|2|-1", + "extent": "4:5-4:10|11998306017310352355|3|0|-1", "type": 53, - "uses": ["5:5-5:6|11998306017310352355|3|20"], + "uses": ["5:5-5:6|11998306017310352355|3|20|-1"], "kind": 13, "storage": 0 }, { @@ -62,10 +62,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "1:14-1:15|11998306017310352355|3|1026", - "extent": "1:10-1:15|11998306017310352355|3|0", + "spell": "1:14-1:15|11998306017310352355|3|1026|-1", + "extent": "1:10-1:15|11998306017310352355|3|0|-1", "type": 53, - "uses": ["2:3-2:4|11998306017310352355|3|20", "7:3-7:4|11998306017310352355|3|20"], + "uses": ["2:3-2:4|11998306017310352355|3|20|-1", "7:3-7:4|11998306017310352355|3|20|-1"], "kind": 253, "storage": 0 }] diff --git a/index_tests/usage/var_usage_static.cc b/index_tests/usage/var_usage_static.cc index 9c825830..396f3ded 100644 --- a/index_tests/usage/var_usage_static.cc +++ b/index_tests/usage/var_usage_static.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [], @@ -47,10 +47,10 @@ OUTPUT: "qual_name_offset": 11, "short_name": "a", "declarations": [], - "spell": "1:12-1:13|0|1|2", - "extent": "1:1-1:13|0|1|0", + "spell": "1:12-1:13|0|1|2|-1", + "extent": "1:1-1:13|0|1|0|-1", "type": 53, - "uses": ["4:3-4:4|4259594751088586730|3|20"], + "uses": ["4:3-4:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 2 }] diff --git a/index_tests/vars/class_member.cc b/index_tests/vars/class_member.cc index 4b3925a7..7bb7bc97 100644 --- a/index_tests/vars/class_member.cc +++ b/index_tests/vars/class_member.cc @@ -14,8 +14,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -26,7 +26,7 @@ OUTPUT: "R": 0 }], "instances": [13799811842374292251], - "uses": ["2:3-2:6|15041163540773201510|2|4"] + "uses": ["2:3-2:6|15041163540773201510|2|4|-1"] }], "usr2var": [{ "usr": 13799811842374292251, @@ -34,8 +34,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "member", "declarations": [], - "spell": "2:8-2:14|15041163540773201510|2|1026", - "extent": "2:3-2:14|15041163540773201510|2|0", + "spell": "2:8-2:14|15041163540773201510|2|1026|-1", + "extent": "2:3-2:14|15041163540773201510|2|0|-1", "type": 15041163540773201510, "uses": [], "kind": 8, diff --git a/index_tests/vars/class_static_member.cc b/index_tests/vars/class_static_member.cc index 1dcb0699..86e09041 100644 --- a/index_tests/vars/class_static_member.cc +++ b/index_tests/vars/class_static_member.cc @@ -16,8 +16,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -25,16 +25,16 @@ OUTPUT: "funcs": [], "vars": [], "instances": [5844987037615239736, 5844987037615239736], - "uses": ["2:10-2:13|15041163540773201510|2|4", "4:1-4:4|0|1|4", "4:6-4:9|0|1|4"] + "uses": ["2:10-2:13|15041163540773201510|2|4|-1", "4:1-4:4|0|1|4|-1", "4:6-4:9|0|1|4|-1"] }], "usr2var": [{ "usr": 5844987037615239736, "detailed_name": "static Foo *Foo::member", "qual_name_offset": 12, "short_name": "member", - "declarations": ["2:15-2:21|15041163540773201510|2|1025"], - "spell": "4:11-4:17|15041163540773201510|2|1026", - "extent": "4:1-4:27|15041163540773201510|2|0", + "declarations": ["2:15-2:21|2:3-2:21|15041163540773201510|2|1025|-1"], + "spell": "4:11-4:17|15041163540773201510|2|1026|-1", + "extent": "4:1-4:27|15041163540773201510|2|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/vars/class_static_member_decl_only.cc b/index_tests/vars/class_static_member_decl_only.cc index b0f84d67..d01c6220 100644 --- a/index_tests/vars/class_static_member_decl_only.cc +++ b/index_tests/vars/class_static_member_decl_only.cc @@ -29,8 +29,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -45,7 +45,7 @@ OUTPUT: "detailed_name": "static int Foo::member", "qual_name_offset": 11, "short_name": "member", - "declarations": ["2:14-2:20|15041163540773201510|2|1025"], + "declarations": ["2:14-2:20|2:3-2:20|15041163540773201510|2|1025|-1"], "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/deduce_auto_type.cc b/index_tests/vars/deduce_auto_type.cc index 3823df90..f76c0460 100644 --- a/index_tests/vars/deduce_auto_type.cc +++ b/index_tests/vars/deduce_auto_type.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "2:6-2:7|0|1|2", - "extent": "2:1-5:2|0|1|0", + "spell": "2:6-2:7|0|1|2|-1", + "extent": "2:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [10601729374837386290, 18422884837902130475], @@ -32,8 +32,8 @@ OUTPUT: "short_name": "Foo", "kind": 5, "declarations": [], - "spell": "1:7-1:10|0|1|2", - "extent": "1:1-1:13|0|1|0", + "spell": "1:7-1:10|0|1|2|-1", + "extent": "1:1-1:13|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -41,7 +41,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [10601729374837386290, 18422884837902130475], - "uses": ["3:16-3:19|880549676430489861|3|4", "4:17-4:20|880549676430489861|3|4"] + "uses": ["3:16-3:19|880549676430489861|3|4|-1", "4:17-4:20|880549676430489861|3|4|-1"] }], "usr2var": [{ "usr": 10601729374837386290, @@ -50,8 +50,8 @@ OUTPUT: "short_name": "x", "hover": "auto x = new Foo()", "declarations": [], - "spell": "3:8-3:9|880549676430489861|3|2", - "extent": "3:3-3:21|880549676430489861|3|0", + "spell": "3:8-3:9|880549676430489861|3|2|-1", + "extent": "3:3-3:21|880549676430489861|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, @@ -63,8 +63,8 @@ OUTPUT: "short_name": "y", "hover": "Foo *y = new Foo()", "declarations": [], - "spell": "4:9-4:10|880549676430489861|3|2", - "extent": "4:3-4:22|880549676430489861|3|0", + "spell": "4:9-4:10|880549676430489861|3|2|-1", + "extent": "4:3-4:22|880549676430489861|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/vars/function_local.cc b/index_tests/vars/function_local.cc index b6197c40..66b96573 100644 --- a/index_tests/vars/function_local.cc +++ b/index_tests/vars/function_local.cc @@ -17,8 +17,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [13198746475679542317], @@ -31,7 +31,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -39,7 +39,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [13198746475679542317], - "uses": ["4:3-4:6|4259594751088586730|3|4"] + "uses": ["4:3-4:6|4259594751088586730|3|4|-1"] }], "usr2var": [{ "usr": 13198746475679542317, @@ -47,8 +47,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "a", "declarations": [], - "spell": "4:8-4:9|4259594751088586730|3|2", - "extent": "4:3-4:9|4259594751088586730|3|0", + "spell": "4:8-4:9|4259594751088586730|3|2|-1", + "extent": "4:3-4:9|4259594751088586730|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 13, diff --git a/index_tests/vars/function_param.cc b/index_tests/vars/function_param.cc index 96a844ad..a9c8683f 100644 --- a/index_tests/vars/function_param.cc +++ b/index_tests/vars/function_param.cc @@ -15,8 +15,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-3:30|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-3:30|0|1|0|-1", "bases": [], "derived": [], "vars": [8730439006497971620, 2525014371090380500], @@ -29,7 +29,7 @@ OUTPUT: "qual_name_offset": 7, "short_name": "Foo", "kind": 23, - "declarations": ["1:8-1:11|0|1|1"], + "declarations": ["1:8-1:11|1:1-1:11|0|1|1|-1"], "alias_of": 0, "bases": [], "derived": [], @@ -37,7 +37,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [8730439006497971620, 2525014371090380500], - "uses": ["3:10-3:13|0|1|4", "3:19-3:22|0|1|4"] + "uses": ["3:10-3:13|0|1|4|-1", "3:19-3:22|0|1|4|-1"] }], "usr2var": [{ "usr": 2525014371090380500, @@ -45,8 +45,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "p1", "declarations": [], - "spell": "3:24-3:26|8908726657907936744|3|1026", - "extent": "3:19-3:26|8908726657907936744|3|0", + "spell": "3:24-3:26|8908726657907936744|3|1026|-1", + "extent": "3:19-3:26|8908726657907936744|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 253, @@ -57,8 +57,8 @@ OUTPUT: "qual_name_offset": 5, "short_name": "p0", "declarations": [], - "spell": "3:15-3:17|8908726657907936744|3|1026", - "extent": "3:10-3:17|8908726657907936744|3|0", + "spell": "3:15-3:17|8908726657907936744|3|1026|-1", + "extent": "3:10-3:17|8908726657907936744|3|0|-1", "type": 15041163540773201510, "uses": [], "kind": 253, diff --git a/index_tests/vars/function_param_unnamed.cc b/index_tests/vars/function_param_unnamed.cc index 6ecfe2fa..48b4f60b 100644 --- a/index_tests/vars/function_param_unnamed.cc +++ b/index_tests/vars/function_param_unnamed.cc @@ -12,8 +12,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-1:22|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-1:22|0|1|0|-1", "bases": [], "derived": [], "vars": [], diff --git a/index_tests/vars/function_shadow_local.cc b/index_tests/vars/function_shadow_local.cc index 27c7b00b..d6ffa4ef 100644 --- a/index_tests/vars/function_shadow_local.cc +++ b/index_tests/vars/function_shadow_local.cc @@ -20,8 +20,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-9:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-9:2|0|1|0|-1", "bases": [], "derived": [], "vars": [1894874819807168345, 4508045017817092115], @@ -50,10 +50,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "2:7-2:8|4259594751088586730|3|2", - "extent": "2:3-2:8|4259594751088586730|3|0", + "spell": "2:7-2:8|4259594751088586730|3|2|-1", + "extent": "2:3-2:8|4259594751088586730|3|0|-1", "type": 53, - "uses": ["3:3-3:4|4259594751088586730|3|20", "8:3-8:4|4259594751088586730|3|20"], + "uses": ["3:3-3:4|4259594751088586730|3|20|-1", "8:3-8:4|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }, { @@ -62,10 +62,10 @@ OUTPUT: "qual_name_offset": 4, "short_name": "a", "declarations": [], - "spell": "5:9-5:10|4259594751088586730|3|2", - "extent": "5:5-5:10|4259594751088586730|3|0", + "spell": "5:9-5:10|4259594751088586730|3|2|-1", + "extent": "5:5-5:10|4259594751088586730|3|0|-1", "type": 53, - "uses": ["6:5-6:6|4259594751088586730|3|20"], + "uses": ["6:5-6:6|4259594751088586730|3|20|-1"], "kind": 13, "storage": 0 }] diff --git a/index_tests/vars/function_shadow_param.cc b/index_tests/vars/function_shadow_param.cc index f2d52211..9ef35ec9 100644 --- a/index_tests/vars/function_shadow_param.cc +++ b/index_tests/vars/function_shadow_param.cc @@ -14,8 +14,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "1:6-1:9|0|1|2", - "extent": "1:1-3:2|0|1|0", + "spell": "1:6-1:9|0|1|2|-1", + "extent": "1:1-3:2|0|1|0|-1", "bases": [], "derived": [], "vars": [5875271969926422921, 11404600766177939811], @@ -44,8 +44,8 @@ OUTPUT: "qual_name_offset": 4, "short_name": "p", "declarations": [], - "spell": "1:14-1:15|11998306017310352355|3|1026", - "extent": "1:10-1:15|11998306017310352355|3|0", + "spell": "1:14-1:15|11998306017310352355|3|1026|-1", + "extent": "1:10-1:15|11998306017310352355|3|0|-1", "type": 53, "uses": [], "kind": 253, @@ -57,8 +57,8 @@ OUTPUT: "short_name": "p", "hover": "int p = 0", "declarations": [], - "spell": "2:9-2:10|11998306017310352355|3|2", - "extent": "2:5-2:14|11998306017310352355|3|0", + "spell": "2:9-2:10|11998306017310352355|3|2|-1", + "extent": "2:5-2:14|11998306017310352355|3|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/global_variable.cc b/index_tests/vars/global_variable.cc index c76dd406..0f563a73 100644 --- a/index_tests/vars/global_variable.cc +++ b/index_tests/vars/global_variable.cc @@ -28,8 +28,8 @@ OUTPUT: "short_name": "global", "hover": "static int global = 0", "declarations": [], - "spell": "1:12-1:18|0|1|2", - "extent": "1:1-1:22|0|1|0", + "spell": "1:12-1:18|0|1|2|-1", + "extent": "1:1-1:22|0|1|0|-1", "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/global_variable_decl_only.cc b/index_tests/vars/global_variable_decl_only.cc index 8ca10b9e..0ecf84a2 100644 --- a/index_tests/vars/global_variable_decl_only.cc +++ b/index_tests/vars/global_variable_decl_only.cc @@ -26,7 +26,7 @@ OUTPUT: "detailed_name": "extern int global", "qual_name_offset": 11, "short_name": "global", - "declarations": ["1:12-1:18|0|1|1"], + "declarations": ["1:12-1:18|1:1-1:18|0|1|1|-1"], "type": 53, "uses": [], "kind": 13, diff --git a/index_tests/vars/type_instance_on_using_type.cc b/index_tests/vars/type_instance_on_using_type.cc index 7a6ebcf6..b924afd5 100644 --- a/index_tests/vars/type_instance_on_using_type.cc +++ b/index_tests/vars/type_instance_on_using_type.cc @@ -19,8 +19,8 @@ OUTPUT: "kind": 12, "storage": 0, "declarations": [], - "spell": "3:6-3:9|0|1|2", - "extent": "3:1-5:2|0|1|0", + "spell": "3:6-3:9|0|1|2|-1", + "extent": "3:1-5:2|0|1|0|-1", "bases": [], "derived": [], "vars": [6975456769752895964], @@ -34,8 +34,8 @@ OUTPUT: "short_name": "S", "kind": 23, "declarations": [], - "spell": "1:8-1:9|0|1|2", - "extent": "1:1-1:12|0|1|0", + "spell": "1:8-1:9|0|1|2|-1", + "extent": "1:1-1:12|0|1|0|-1", "alias_of": 0, "bases": [], "derived": [], @@ -43,7 +43,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [], - "uses": ["2:11-2:12|0|1|4"] + "uses": ["2:11-2:12|0|1|4|-1"] }, { "usr": 7434820806199665424, "detailed_name": "using F = S", @@ -51,8 +51,8 @@ OUTPUT: "short_name": "F", "kind": 252, "declarations": [], - "spell": "2:7-2:8|0|1|2", - "extent": "2:1-2:12|0|1|0", + "spell": "2:7-2:8|0|1|2|-1", + "extent": "2:1-2:12|0|1|0|-1", "alias_of": 4750332761459066907, "bases": [], "derived": [], @@ -60,7 +60,7 @@ OUTPUT: "funcs": [], "vars": [], "instances": [6975456769752895964], - "uses": ["4:3-4:4|4654328188330986029|3|4"] + "uses": ["4:3-4:4|4654328188330986029|3|4|-1"] }], "usr2var": [{ "usr": 6975456769752895964, @@ -68,8 +68,8 @@ OUTPUT: "qual_name_offset": 2, "short_name": "a", "declarations": [], - "spell": "4:5-4:6|4654328188330986029|3|2", - "extent": "4:3-4:6|4654328188330986029|3|0", + "spell": "4:5-4:6|4654328188330986029|3|2|-1", + "extent": "4:3-4:6|4654328188330986029|3|0|-1", "type": 7434820806199665424, "uses": [], "kind": 13, diff --git a/src/clang_complete.cc b/src/clang_complete.cc index c24f9c7a..b66a01f8 100644 --- a/src/clang_complete.cc +++ b/src/clang_complete.cc @@ -13,16 +13,17 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" -#include "clang_utils.h" +#include "clang_tu.hh" #include "filesystem.hh" #include "log.hh" +#include "match.h" #include "platform.h" -#include -#include +#include #include +#include #include #include #include @@ -31,541 +32,393 @@ using namespace clang; using namespace llvm; #include +#include +#include #include +namespace chrono = std::chrono; +namespace ccls { namespace { std::string StripFileType(const std::string &path) { SmallString<128> Ret; sys::path::append(Ret, sys::path::parent_path(path), sys::path::stem(path)); - return Ret.str(); + return sys::path::convert_to_slash(Ret); } -unsigned GetCompletionPriority(const CodeCompletionString &CCS, - CXCursorKind result_kind, - const std::optional &typedText) { - unsigned priority = CCS.getPriority(); - if (CCS.getAvailability() != CXAvailability_Available || - result_kind == CXCursor_Destructor || - result_kind == CXCursor_ConversionFunction || - (result_kind == CXCursor_CXXMethod && typedText && - StartsWith(*typedText, "operator"))) - priority *= 100; - return priority; +bool LocationInRange(SourceLocation L, CharSourceRange R, + const SourceManager &M) { + assert(R.isCharRange()); + if (!R.isValid() || M.getFileID(R.getBegin()) != M.getFileID(R.getEnd()) || + M.getFileID(R.getBegin()) != M.getFileID(L)) + return false; + return L != R.getEnd() && M.isPointWithin(L, R.getBegin(), R.getEnd()); } -lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) { - switch (cursor_kind) { - case CXCursor_UnexposedDecl: - return lsCompletionItemKind::Text; - - case CXCursor_StructDecl: - case CXCursor_UnionDecl: - return lsCompletionItemKind::Struct; - case CXCursor_ClassDecl: - return lsCompletionItemKind::Class; - case CXCursor_EnumDecl: - return lsCompletionItemKind::Enum; - case CXCursor_FieldDecl: - return lsCompletionItemKind::Field; - case CXCursor_EnumConstantDecl: - return lsCompletionItemKind::EnumMember; - case CXCursor_FunctionDecl: - return lsCompletionItemKind::Function; - case CXCursor_VarDecl: - case CXCursor_ParmDecl: - return lsCompletionItemKind::Variable; - case CXCursor_ObjCInterfaceDecl: - return lsCompletionItemKind::Interface; - - case CXCursor_ObjCInstanceMethodDecl: - case CXCursor_CXXMethod: - case CXCursor_ObjCClassMethodDecl: - return lsCompletionItemKind::Method; - - case CXCursor_FunctionTemplate: - return lsCompletionItemKind::Function; - - case CXCursor_Constructor: - case CXCursor_Destructor: - case CXCursor_ConversionFunction: - return lsCompletionItemKind::Constructor; - - case CXCursor_ObjCIvarDecl: - return lsCompletionItemKind::Variable; - - case CXCursor_ClassTemplate: - case CXCursor_ClassTemplatePartialSpecialization: - case CXCursor_UsingDeclaration: - case CXCursor_TypedefDecl: - case CXCursor_TypeAliasDecl: - case CXCursor_TypeAliasTemplateDecl: - case CXCursor_ObjCCategoryDecl: - case CXCursor_ObjCProtocolDecl: - case CXCursor_ObjCImplementationDecl: - case CXCursor_ObjCCategoryImplDecl: - return lsCompletionItemKind::Class; - - case CXCursor_ObjCPropertyDecl: - return lsCompletionItemKind::Property; - - case CXCursor_MacroInstantiation: - case CXCursor_MacroDefinition: - return lsCompletionItemKind::Interface; - - case CXCursor_Namespace: - case CXCursor_NamespaceAlias: - case CXCursor_NamespaceRef: - return lsCompletionItemKind::Module; - - case CXCursor_MemberRef: - case CXCursor_TypeRef: - case CXCursor_ObjCSuperClassRef: - case CXCursor_ObjCProtocolRef: - case CXCursor_ObjCClassRef: - return lsCompletionItemKind::Reference; - - // return lsCompletionItemKind::Unit; - // return lsCompletionItemKind::Value; - // return lsCompletionItemKind::Keyword; - // return lsCompletionItemKind::Snippet; - // return lsCompletionItemKind::Color; - // return lsCompletionItemKind::File; - - case CXCursor_NotImplemented: - case CXCursor_OverloadCandidate: - return lsCompletionItemKind::Text; - - case CXCursor_TemplateTypeParameter: - case CXCursor_TemplateTemplateParameter: - return lsCompletionItemKind::TypeParameter; - - default: - LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind; - return lsCompletionItemKind::Text; +CharSourceRange DiagnosticRange(const clang::Diagnostic &D, const LangOptions &L) { + auto &M = D.getSourceManager(); + auto Loc = M.getFileLoc(D.getLocation()); + // Accept the first range that contains the location. + for (const auto &CR : D.getRanges()) { + auto R = Lexer::makeFileCharRange(CR, M, L); + if (LocationInRange(Loc, R, M)) + return R; } -} - -void BuildCompletionItemTexts(std::vector &out, - CodeCompletionString &CCS, - bool include_snippets) { - assert(!out.empty()); - auto out_first = out.size() - 1; - - std::string result_type; - - for (unsigned i = 0, num_chunks = CCS.size(); i < num_chunks; ++i) { - const CodeCompletionString::Chunk &Chunk = CCS[i]; - CodeCompletionString::ChunkKind Kind = Chunk.Kind; - std::string text; - switch (Kind) { - case CodeCompletionString::CK_TypedText: - case CodeCompletionString::CK_Text: - case CodeCompletionString::CK_Placeholder: - case CodeCompletionString::CK_Informative: - if (Chunk.Text) - text = Chunk.Text; - for (auto i = out_first; i < out.size(); i++) { - // first TypedText is used for filtering - if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText) - out[i].filterText = text; - if (Kind == CodeCompletionString::CK_Placeholder) - out[i].parameters_.push_back(text); - } - break; - case CodeCompletionString::CK_ResultType: - if (Chunk.Text) - result_type = Chunk.Text; - continue; - case CodeCompletionString::CK_CurrentParameter: - // We have our own parsing logic for active parameter. This doesn't seem - // to be very reliable. - continue; - case CodeCompletionString::CK_Optional: { - // duplicate last element, the recursive call will complete it - out.push_back(out.back()); - BuildCompletionItemTexts(out, *Chunk.Optional, include_snippets); - continue; - } - // clang-format off - case CodeCompletionString::CK_LeftParen: text = '('; break; - case CodeCompletionString::CK_RightParen: text = ')'; break; - case CodeCompletionString::CK_LeftBracket: text = '['; break; - case CodeCompletionString::CK_RightBracket: text = ']'; break; - case CodeCompletionString::CK_LeftBrace: text = '{'; break; - case CodeCompletionString::CK_RightBrace: text = '}'; break; - case CodeCompletionString::CK_LeftAngle: text = '<'; break; - case CodeCompletionString::CK_RightAngle: text = '>'; break; - case CodeCompletionString::CK_Comma: text = ", "; break; - case CodeCompletionString::CK_Colon: text = ':'; break; - case CodeCompletionString::CK_SemiColon: text = ';'; break; - case CodeCompletionString::CK_Equal: text = '='; break; - case CodeCompletionString::CK_HorizontalSpace: text = ' '; break; - case CodeCompletionString::CK_VerticalSpace: text = ' '; break; - // clang-format on - } - - if (Kind != CodeCompletionString::CK_Informative) - for (auto i = out_first; i < out.size(); ++i) { - out[i].label += text; - if (!include_snippets && !out[i].parameters_.empty()) - continue; - - if (Kind == CodeCompletionString::CK_Placeholder) { - out[i].insertText += "${" + - std::to_string(out[i].parameters_.size()) + ":" + - text + "}"; - out[i].insertTextFormat = lsInsertTextFormat::Snippet; - } else { - out[i].insertText += text; - } - } + // The range may be given as a fixit hint instead. + for (const auto &F : D.getFixItHints()) { + auto R = Lexer::makeFileCharRange(F.RemoveRange, M, L); + if (LocationInRange(Loc, R, M)) + return R; } - - if (result_type.size()) - for (auto i = out_first; i < out.size(); ++i) { - // ' : ' for variables, - // ' -> ' (trailing return type-like) for functions - out[i].label += (out[i].label == out[i].filterText ? " : " : " -> "); - out[i].label += result_type; - } + // If no suitable range is found, just use the token at the location. + auto R = Lexer::makeFileCharRange(CharSourceRange::getTokenRange(Loc), M, L); + if (!R.isValid()) // Fall back to location only, let the editor deal with it. + R = CharSourceRange::getCharRange(Loc); + return R; } -// |do_insert|: if |!do_insert|, do not append strings to |insert| after -// a placeholder. -void BuildDetailString(const CodeCompletionString &CCS, lsCompletionItem &item, - bool &do_insert, std::vector *parameters, - bool include_snippets, int &angle_stack) { - for (unsigned i = 0, num_chunks = CCS.size(); i < num_chunks; ++i) { - const CodeCompletionString::Chunk &Chunk = CCS[i]; - CodeCompletionString::ChunkKind Kind = Chunk.Kind; - const char *text = nullptr; - switch (Kind) { - case CodeCompletionString::CK_TypedText: - item.label = Chunk.Text; - [[fallthrough]]; - case CodeCompletionString::CK_Text: - item.detail += Chunk.Text; - if (do_insert) - item.insertText += Chunk.Text; - break; - case CodeCompletionString::CK_Placeholder: { - parameters->push_back(Chunk.Text); - item.detail += Chunk.Text; - // Add parameter declarations as snippets if enabled - if (include_snippets) { - item.insertText += - "${" + std::to_string(parameters->size()) + ":" + Chunk.Text + "}"; - item.insertTextFormat = lsInsertTextFormat::Snippet; - } else - do_insert = false; - break; - } - case CodeCompletionString::CK_Informative: - item.detail += Chunk.Text; - break; - case CodeCompletionString::CK_Optional: { - // Do not add text to insert string if we're in angle brackets. - bool should_insert = do_insert && angle_stack == 0; - BuildDetailString(*Chunk.Optional, item, should_insert, parameters, - include_snippets, angle_stack); - break; - } - case CodeCompletionString::CK_ResultType: - item.detail = Chunk.Text + item.detail + " "; - break; - case CodeCompletionString::CK_CurrentParameter: - // We have our own parsing logic for active parameter. This doesn't seem - // to be very reliable. - break; - // clang-format off - case CodeCompletionString::CK_LeftParen: text = "("; break; - case CodeCompletionString::CK_RightParen: text = ")"; break; - case CodeCompletionString::CK_LeftBracket: text = "["; break; - case CodeCompletionString::CK_RightBracket: text = "]"; break; - case CodeCompletionString::CK_LeftBrace: text = "{"; break; - case CodeCompletionString::CK_RightBrace: text = "}"; break; - case CodeCompletionString::CK_LeftAngle: text = "<"; angle_stack++; break; - case CodeCompletionString::CK_RightAngle: text = ">"; angle_stack--; break; - case CodeCompletionString::CK_Comma: text = ", "; break; - case CodeCompletionString::CK_Colon: text = ":"; break; - case CodeCompletionString::CK_SemiColon: text = ";"; break; - case CodeCompletionString::CK_Equal: text = "="; break; - case CodeCompletionString::CK_HorizontalSpace: - case CodeCompletionString::CK_VerticalSpace: text = " "; break; - // clang-format on - } - if (text) { - item.detail += text; - if (do_insert && include_snippets) - item.insertText += text; - } + + +class StoreDiags : public DiagnosticConsumer { + const LangOptions *LangOpts; + std::optional last; + std::vector output; + std::string path; + std::unordered_map FID2concerned; + void Flush() { + if (!last) + return; + bool mentions = last->concerned || last->edits.size(); + if (!mentions) + for (auto &N : last->notes) + if (N.concerned) + mentions = true; + if (mentions) + output.push_back(std::move(*last)); + last.reset(); } -} - -class CaptureCompletionResults : public CodeCompleteConsumer { - std::shared_ptr Alloc; - CodeCompletionTUInfo CCTUInfo; - public: - std::vector ls_items; + StoreDiags(std::string path) : path(path) {} + std::vector Take() { + return std::move(output); + } + bool IsConcerned(const SourceManager &SM, SourceLocation L) { + FileID FID = SM.getFileID(L); + auto it = FID2concerned.try_emplace(FID.getHashValue()); + if (it.second) { + const FileEntry *FE = SM.getFileEntryForID(FID); + it.first->second = FE && PathFromFileEntry(*FE) == path; + } + return it.first->second; + } + void BeginSourceFile(const LangOptions &Opts, const Preprocessor *) override { + LangOpts = &Opts; + } + void EndSourceFile() override { + Flush(); + } + void HandleDiagnostic(DiagnosticsEngine::Level Level, + const Diagnostic &Info) override { + DiagnosticConsumer::HandleDiagnostic(Level, Info); + SourceLocation L = Info.getLocation(); + if (!L.isValid()) return; + const SourceManager &SM = Info.getSourceManager(); + StringRef Filename = SM.getFilename(Info.getLocation()); + bool concerned = IsConcerned(SM, Info.getLocation()); + auto fillDiagBase = [&](DiagBase &d) { + llvm::SmallString<64> Message; + Info.FormatDiagnostic(Message); + d.range = + FromCharSourceRange(SM, *LangOpts, DiagnosticRange(Info, *LangOpts)); + d.message = Message.str(); + d.concerned = concerned; + d.file = Filename; + d.level = Level; + d.category = DiagnosticIDs::getCategoryNumberForDiag(Info.getID()); + }; - CaptureCompletionResults(const CodeCompleteOptions &Opts) - : CodeCompleteConsumer(Opts, false), - Alloc(std::make_shared()), - CCTUInfo(Alloc) {} - - void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, - CodeCompletionResult *Results, - unsigned NumResults) override { - ls_items.reserve(NumResults); - for (unsigned i = 0; i != NumResults; i++) { - CodeCompletionString *CCS = Results[i].CreateCodeCompletionString( - S, Context, getAllocator(), getCodeCompletionTUInfo(), - includeBriefComments()); - if (CCS->getAvailability() == CXAvailability_NotAvailable) - continue; - - lsCompletionItem ls_item; - ls_item.kind = GetCompletionKind(Results[i].CursorKind); - if (const char *brief = CCS->getBriefComment()) - ls_item.documentation = brief; - - // label/detail/filterText/insertText/priority - if (g_config->completion.detailedLabel) { - ls_item.detail = CCS->getParentContextName().str(); - - size_t first_idx = ls_items.size(); - ls_items.push_back(ls_item); - BuildCompletionItemTexts(ls_items, *CCS, - g_config->client.snippetSupport); - - for (size_t j = first_idx; j < ls_items.size(); j++) { - if (g_config->client.snippetSupport && - ls_items[j].insertTextFormat == lsInsertTextFormat::Snippet) - ls_items[j].insertText += "$0"; - ls_items[j].priority_ = GetCompletionPriority( - *CCS, Results[i].CursorKind, ls_items[j].filterText); - } - } else { - bool do_insert = true; - int angle_stack = 0; - BuildDetailString(*CCS, ls_item, do_insert, &ls_item.parameters_, - g_config->client.snippetSupport, angle_stack); - if (g_config->client.snippetSupport && - ls_item.insertTextFormat == lsInsertTextFormat::Snippet) - ls_item.insertText += "$0"; - ls_item.priority_ = - GetCompletionPriority(*CCS, Results[i].CursorKind, ls_item.label); - ls_items.push_back(ls_item); + auto addFix = [&](bool SyntheticMessage) -> bool { + if (!concerned) + return false; + for (const FixItHint &FixIt : Info.getFixItHints()) { + if (!IsConcerned(SM, FixIt.RemoveRange.getBegin())) + return false; + lsTextEdit edit; + edit.newText = FixIt.CodeToInsert; + auto r = FromCharSourceRange(SM, *LangOpts, FixIt.RemoveRange); + edit.range = + lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}}; + last->edits.push_back(std::move(edit)); } + return true; + }; + + if (Level == DiagnosticsEngine::Note || Level == DiagnosticsEngine::Remark) { + if (Info.getFixItHints().size()) { + addFix(false); + } else { + Note &n = last->notes.emplace_back(); + fillDiagBase(n); + } + } else { + Flush(); + last = Diag(); + fillDiagBase(*last); + if (!Info.getFixItHints().empty()) + addFix(true); } } - - void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, - OverloadCandidate *Candidates, - unsigned NumCandidates) override {} - - CodeCompletionAllocator &getAllocator() override { return *Alloc; } - - CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } }; -void TryEnsureDocumentParsed(ClangCompleteManager *manager, - std::shared_ptr session, - std::unique_ptr *tu, - bool diagnostic) { - // Nothing to do. We already have a translation unit. - if (*tu) - return; +std::unique_ptr BuildCompilerInstance( + CompletionSession &session, std::unique_ptr CI, + DiagnosticConsumer &DC, const WorkingFiles::Snapshot &snapshot, + std::vector> &Bufs) { + std::string main = ResolveIfRelative( + session.file.directory, + sys::path::convert_to_slash(CI->getFrontendOpts().Inputs[0].getFile())); + for (auto &file : snapshot.files) { + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(file.content)); + if (file.filename == main) + if (auto Preamble = session.GetPreamble()) { +#if LLVM_VERSION_MAJOR >= 7 + Preamble->Preamble.OverridePreamble(*CI, session.FS, + Bufs.back().get()); +#else + Preamble->Preamble.AddImplicitPreamble(*CI, session.FS, + Bufs.back().get()); +#endif + continue; + } + CI->getPreprocessorOpts().addRemappedFile(file.filename, + Bufs.back().get()); + } - const auto &args = session->file.args; - WorkingFiles::Snapshot snapshot = session->working_files->AsSnapshot( - {StripFileType(session->file.filename)}); - - LOG_S(INFO) << "create " << (diagnostic ? "diagnostic" : "completion") - << " TU for " << session->file.filename; - *tu = ClangTranslationUnit::Create(session->file.filename, args, snapshot, - diagnostic); + auto Clang = std::make_unique(session.PCH); + Clang->setInvocation(std::move(CI)); + Clang->setVirtualFileSystem(session.FS); + Clang->createDiagnostics(&DC, false); + Clang->setTarget(TargetInfo::CreateTargetInfo( + Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); + if (!Clang->hasTarget()) + return nullptr; + // Construct SourceManager with UserFilesAreVolatile: true because otherwise + // RequiresNullTerminator: true may cause out-of-bounds read when a file is + // mmap'ed but is saved concurrently. + Clang->createFileManager(); + Clang->setSourceManager(new SourceManager(Clang->getDiagnostics(), + Clang->getFileManager(), true)); + return Clang; } -void CompletionPreloadMain(ClangCompleteManager *completion_manager) { - while (true) { - // Fetching the completion request blocks until we have a request. - auto request = completion_manager->preload_requests_.Dequeue(); +bool Parse(CompilerInstance &Clang) { + SyntaxOnlyAction Action; + if (!Action.BeginSourceFile(Clang, Clang.getFrontendOpts().Inputs[0])) + return false; + if (!Action.Execute()) + return false; + Action.EndSourceFile(); + return true; +} - // If we don't get a session then that means we don't care about the file - // anymore - abandon the request. +void CompletionPreloadMain(CompletionManager *manager) { + while (true) { + auto request = manager->preload_requests_.Dequeue(); + + bool is_open = false; std::shared_ptr session = - completion_manager->TryGetSession(request.path, - false /*mark_as_completion*/, - false /*create_if_needed*/); + manager->TryGetSession(request.path, true, &is_open); if (!session) continue; - // Note: we only preload completion. We emit diagnostics for the - // completion preload though. - CompletionSession::Tu *tu = &session->completion; + const auto &args = session->file.args; + WorkingFiles::Snapshot snapshot = + session->wfiles->AsSnapshot({StripFileType(session->file.filename)}); + if (std::unique_ptr CI = + BuildCompilerInvocation(args, session->FS)) + session->BuildPreamble(*CI, request.path); - // If we've parsed it more recently than the request time, don't bother - // reparsing. - if (tu->last_parsed_at && *tu->last_parsed_at > request.request_time) - continue; - - std::unique_ptr parsing; - TryEnsureDocumentParsed(completion_manager, session, &parsing, false); - - // Activate new translation unit. - std::lock_guard lock(tu->lock); - tu->last_parsed_at = std::chrono::high_resolution_clock::now(); - tu->tu = std::move(parsing); + int debounce = + is_open ? g_config->diagnostics.onOpen : g_config->diagnostics.onSave; + if (debounce >= 0) { + lsTextDocumentIdentifier document; + document.uri = lsDocumentUri::FromPath(request.path); + manager->DiagnosticsUpdate(request.path, debounce); + } } } -void CompletionQueryMain(ClangCompleteManager *completion_manager) { +void CompletionMain(CompletionManager *manager) { while (true) { // Fetching the completion request blocks until we have a request. - std::unique_ptr request = - completion_manager->completion_request_.Dequeue(); + std::unique_ptr request = + manager->completion_request_.Dequeue(); // Drop older requests if we're not buffering. while (g_config->completion.dropOldRequests && - !completion_manager->completion_request_.IsEmpty()) { - completion_manager->on_dropped_(request->id); - request = completion_manager->completion_request_.Dequeue(); + !manager->completion_request_.IsEmpty()) { + manager->on_dropped_(request->id); + request->Consumer.reset(); + request->on_complete(nullptr); + request = manager->completion_request_.Dequeue(); } std::string path = request->document.uri.GetPath(); std::shared_ptr session = - completion_manager->TryGetSession(path, true /*mark_as_completion*/, - true /*create_if_needed*/); + manager->TryGetSession(path, false); - std::lock_guard lock(session->completion.lock); - TryEnsureDocumentParsed(completion_manager, session, - &session->completion.tu, false); + std::unique_ptr CI = + BuildCompilerInvocation(session->file.args, session->FS); + if (!CI) + continue; + auto &FOpts = CI->getFrontendOpts(); + FOpts.CodeCompleteOpts = request->CCOpts; + FOpts.CodeCompletionAt.FileName = path; + FOpts.CodeCompletionAt.Line = request->position.line + 1; + FOpts.CodeCompletionAt.Column = request->position.character + 1; + FOpts.SkipFunctionBodies = true; + CI->getLangOpts()->CommentOpts.ParseAllComments = true; - // It is possible we failed to create the document despite - // |TryEnsureDocumentParsed|. - if (ClangTranslationUnit *tu = session->completion.tu.get()) { - WorkingFiles::Snapshot snapshot = - completion_manager->working_files_->AsSnapshot({StripFileType(path)}); - IntrusiveRefCntPtr FileMgr(&tu->Unit->getFileManager()); - IntrusiveRefCntPtr DiagOpts(new DiagnosticOptions()); - IntrusiveRefCntPtr Diag(new DiagnosticsEngine( - IntrusiveRefCntPtr(new DiagnosticIDs), &*DiagOpts)); - // StoreDiags Diags; - // IntrusiveRefCntPtr DiagE = - // CompilerInstance::createDiagnostics(DiagOpts.get(), &Diags, false); + DiagnosticConsumer DC; + WorkingFiles::Snapshot snapshot = + manager->working_files_->AsSnapshot({StripFileType(path)}); + std::vector> Bufs; + auto Clang = BuildCompilerInstance(*session, std::move(CI), DC, snapshot, Bufs); + if (!Clang) + continue; - IntrusiveRefCntPtr SrcMgr( - new SourceManager(*Diag, *FileMgr)); - std::vector Remapped = GetRemapped(snapshot); - SmallVector Diagnostics; - SmallVector TemporaryBuffers; + Clang->setCodeCompletionConsumer(request->Consumer.release()); + if (!Parse(*Clang)) + continue; + for (auto &Buf : Bufs) + Buf.release(); - CodeCompleteOptions Opts; - LangOptions LangOpts; - Opts.IncludeBriefComments = true; -#if LLVM_VERSION_MAJOR >= 7 - Opts.LoadExternal = true; - Opts.IncludeFixIts = true; -#endif - CaptureCompletionResults capture(Opts); - tu->Unit->CodeComplete(session->file.filename, request->position.line + 1, - request->position.character + 1, Remapped, - /*IncludeMacros=*/true, - /*IncludeCodePatterns=*/false, - /*IncludeBriefComments=*/g_config->index.comments, - capture, tu->PCHCO, *Diag, LangOpts, *SrcMgr, - *FileMgr, Diagnostics, TemporaryBuffers); - request->on_complete(capture.ls_items, false /*is_cached_result*/); - // completion_manager->on_diagnostic_(session->file.filename, - // Diags.take()); - } + request->on_complete(&Clang->getCodeCompletionConsumer()); } } -void DiagnosticQueryMain(ClangCompleteManager *manager) { +llvm::StringRef diagLeveltoString(DiagnosticsEngine::Level Lvl) { + switch (Lvl) { + case DiagnosticsEngine::Ignored: + return "ignored"; + case DiagnosticsEngine::Note: + return "note"; + case DiagnosticsEngine::Remark: + return "remark"; + case DiagnosticsEngine::Warning: + return "warning"; + case DiagnosticsEngine::Error: + return "error"; + case DiagnosticsEngine::Fatal: + return "fatal error"; + } +} + +void printDiag(llvm::raw_string_ostream &OS, const DiagBase &d) { + if (d.concerned) + OS << llvm::sys::path::filename(d.file); + else + OS << d.file; + auto pos = d.range.start; + OS << ":" << (pos.line + 1) << ":" << (pos.column + 1) << ":" + << (d.concerned ? " " : "\n"); + OS << diagLeveltoString(d.level) << ": " << d.message; +} + +void DiagnosticMain(CompletionManager *manager) { while (true) { - // Fetching the completion request blocks until we have a request. - ClangCompleteManager::DiagnosticRequest request = + CompletionManager::DiagnosticRequest request = manager->diagnostic_request_.Dequeue(); - if (!g_config->diagnostics.onType) + const std::string &path = request.path; + int64_t wait = request.wait_until - + chrono::duration_cast( + chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + if (wait > 0) + std::this_thread::sleep_for(chrono::duration( + std::min(wait, request.debounce))); + + std::shared_ptr session = + manager->TryGetSession(path, false); + + std::unique_ptr CI = + BuildCompilerInvocation(session->file.args, session->FS); + if (!CI) continue; - std::string path = request.document.uri.GetPath(); - - std::shared_ptr session = manager->TryGetSession( - path, true /*mark_as_completion*/, true /*create_if_needed*/); - - // At this point, we must have a translation unit. Block until we have one. - std::lock_guard lock(session->diagnostics.lock); - TryEnsureDocumentParsed(manager, session, &session->diagnostics.tu, true); - - // It is possible we failed to create the document despite - // |TryEnsureDocumentParsed|. - ClangTranslationUnit *tu = session->diagnostics.tu.get(); - if (!tu) - continue; - + CI->getDiagnosticOpts().IgnoreWarnings = false; + CI->getLangOpts()->SpellChecking = g_config->diagnostics.spellChecking; + StoreDiags DC(path); WorkingFiles::Snapshot snapshot = manager->working_files_->AsSnapshot({StripFileType(path)}); - llvm::CrashRecoveryContext CRC; - if (tu->Reparse(CRC, snapshot)) { - LOG_S(ERROR) << "Reparsing translation unit for diagnostics failed for " - << path; + std::vector> Bufs; + auto Clang = BuildCompilerInstance(*session, std::move(CI), DC, snapshot, Bufs); + if (!Clang) continue; - } + if (!Parse(*Clang)) + continue; + for (auto &Buf : Bufs) + Buf.release(); - auto &LangOpts = tu->Unit->getLangOpts(); - std::vector ls_diags; - for (ASTUnit::stored_diag_iterator I = tu->Unit->stored_diag_begin(), - E = tu->Unit->stored_diag_end(); - I != E; ++I) { - FullSourceLoc FLoc = I->getLocation(); - if (!FLoc.isValid()) // why? - continue; - const FileEntry *FE = FLoc.getFileEntry(); - if (!FE || FileName(*FE) != path) - continue; - const auto &SM = FLoc.getManager(); - SourceRange R; - for (const auto &CR : I->getRanges()) { - auto RT = Lexer::makeFileCharRange(CR, SM, LangOpts); - if (SM.isPointWithin(FLoc, RT.getBegin(), RT.getEnd())) { - R = CR.getAsRange(); - break; - } - } - Range r = R.isValid() ? FromCharRange(SM, LangOpts, R) - : FromTokenRange(SM, LangOpts, {FLoc, FLoc}); - lsDiagnostic ls_diag; - ls_diag.range = - lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}}; - switch (I->getLevel()) { + auto Fill = [](const DiagBase &d, lsDiagnostic &ret) { + ret.range = lsRange{{d.range.start.line, d.range.start.column}, + {d.range.end.line, d.range.end.column}}; + switch (d.level) { case DiagnosticsEngine::Ignored: // llvm_unreachable - case DiagnosticsEngine::Note: case DiagnosticsEngine::Remark: - ls_diag.severity = lsDiagnosticSeverity::Information; - continue; + ret.severity = lsDiagnosticSeverity::Hint; + break; + case DiagnosticsEngine::Note: + ret.severity = lsDiagnosticSeverity::Information; + break; case DiagnosticsEngine::Warning: - ls_diag.severity = lsDiagnosticSeverity::Warning; + ret.severity = lsDiagnosticSeverity::Warning; break; case DiagnosticsEngine::Error: case DiagnosticsEngine::Fatal: - ls_diag.severity = lsDiagnosticSeverity::Error; + ret.severity = lsDiagnosticSeverity::Error; + break; } - ls_diag.message = I->getMessage().str(); - for (const FixItHint &FixIt : I->getFixIts()) { - lsTextEdit edit; - edit.newText = FixIt.CodeToInsert; - r = FromCharSourceRange(SM, LangOpts, FixIt.RemoveRange); - edit.range = - lsRange{{r.start.line, r.start.column}, {r.end.line, r.end.column}}; - ls_diag.fixits_.push_back(edit); + ret.code = d.category; + return ret; + }; + + std::vector diags = DC.Take(); + if (std::shared_ptr preamble = session->GetPreamble()) + diags.insert(diags.end(), preamble->diags.begin(), preamble->diags.end()); + std::vector ls_diags; + for (auto &d : diags) { + if (!d.concerned) + continue; + std::string buf; + llvm::raw_string_ostream OS(buf); + lsDiagnostic &ls_diag = ls_diags.emplace_back(); + Fill(d, ls_diag); + ls_diag.fixits_ = d.edits; + OS << d.message; + for (auto &n : d.notes) { + OS << "\n\n"; + printDiag(OS, n); } - ls_diags.push_back(ls_diag); + OS.flush(); + ls_diag.message = std::move(buf); + for (auto &n : d.notes) { + if (!n.concerned) + continue; + lsDiagnostic &ls_diag1 = ls_diags.emplace_back(); + Fill(n, ls_diag1); + OS << n.message << "\n\n"; + printDiag(OS, d); + OS.flush(); + ls_diag1.message = std::move(buf); + } + } + + { + std::lock_guard lock(session->wfiles->files_mutex); + if (WorkingFile *wfile = session->wfiles->GetFileByFilenameNoLock(path)) + wfile->diagnostics_ = ls_diags; } manager->on_diagnostic_(path, ls_diags); } @@ -573,175 +426,159 @@ void DiagnosticQueryMain(ClangCompleteManager *manager) { } // namespace -ClangCompleteManager::ClangCompleteManager(Project *project, - WorkingFiles *working_files, - OnDiagnostic on_diagnostic, - OnDropped on_dropped) +std::shared_ptr CompletionSession::GetPreamble() { + std::lock_guard lock(mutex); + return preamble; +} + +void CompletionSession::BuildPreamble(CompilerInvocation &CI, + const std::string &main) { + std::shared_ptr OldP = GetPreamble(); + std::string content = wfiles->GetContent(main); + std::unique_ptr Buf = + llvm::MemoryBuffer::getMemBuffer(content); + auto Bounds = ComputePreambleBounds(*CI.getLangOpts(), Buf.get(), 0); + if (OldP && OldP->Preamble.CanReuse(CI, Buf.get(), Bounds, FS.get())) + return; + CI.getDiagnosticOpts().IgnoreWarnings = false; + CI.getFrontendOpts().SkipFunctionBodies = true; + CI.getLangOpts()->CommentOpts.ParseAllComments = true; +#if LLVM_VERSION_MAJOR >= 7 + CI.getPreprocessorOpts().WriteCommentListToPCH = false; +#endif + + StoreDiags DC(main); + IntrusiveRefCntPtr DE = + CompilerInstance::createDiagnostics(&CI.getDiagnosticOpts(), &DC, false); + PreambleCallbacks PP; + if (auto NewPreamble = PrecompiledPreamble::Build(CI, Buf.get(), Bounds, + *DE, FS, PCH, true, PP)) { + std::lock_guard lock(mutex); + preamble = + std::make_shared(std::move(*NewPreamble), DC.Take()); + } +} + +} // namespace ccls + +CompletionManager::CompletionManager(Project *project, + WorkingFiles *working_files, + OnDiagnostic on_diagnostic, + OnDropped on_dropped) : project_(project), working_files_(working_files), on_diagnostic_(on_diagnostic), on_dropped_(on_dropped), - preloaded_sessions_(kMaxPreloadedSessions), - completion_sessions_(kMaxCompletionSessions) { + preloads(kMaxPreloadedSessions), + sessions(kMaxCompletionSessions), + PCH(std::make_shared()) { std::thread([&]() { - set_thread_name("comp-query"); - CompletionQueryMain(this); + set_thread_name("comp"); + ccls::CompletionMain(this); }) .detach(); std::thread([&]() { set_thread_name("comp-preload"); - CompletionPreloadMain(this); + ccls::CompletionPreloadMain(this); }) .detach(); std::thread([&]() { - set_thread_name("diag-query"); - DiagnosticQueryMain(this); + set_thread_name("diag"); + ccls::DiagnosticMain(this); }) .detach(); } -void ClangCompleteManager::CodeComplete( - const lsRequestId &id, - const lsTextDocumentPositionParams &completion_location, - const OnComplete &on_complete) { - completion_request_.PushBack(std::make_unique( - id, completion_location.textDocument, completion_location.position, - on_complete)); -} - -void ClangCompleteManager::DiagnosticsUpdate( - const lsTextDocumentIdentifier &document) { - bool has = false; - diagnostic_request_.Iterate([&](const DiagnosticRequest &request) { - if (request.document.uri == document.uri) - has = true; - }); - if (!has) - diagnostic_request_.PushBack(DiagnosticRequest{document}, - true /*priority*/); -} - -void ClangCompleteManager::NotifyView(const std::string &filename) { - // - // On view, we reparse only if the file has not been parsed. The existence of - // a CompletionSession instance implies the file is already parsed or will be - // parsed soon. - // - - // Only reparse the file if we create a new CompletionSession. - if (EnsureCompletionOrCreatePreloadSession(filename)) - preload_requests_.PushBack(PreloadRequest(filename), true); -} - -void ClangCompleteManager::NotifyEdit(const std::string &filename) { - // - // We treat an edit like a view, because the completion logic will handle - // moving the CompletionSession instance from preloaded to completion - // storage. - // - - NotifyView(filename); -} - -void ClangCompleteManager::NotifySave(const std::string &filename) { - // - // On save, always reparse. - // - - EnsureCompletionOrCreatePreloadSession(filename); - preload_requests_.PushBack(PreloadRequest(filename), true); -} - -void ClangCompleteManager::NotifyClose(const std::string &filename) { - // - // On close, we clear any existing CompletionSession instance. - // - - std::lock_guard lock(sessions_lock_); - - // Take and drop. It's okay if we don't actually drop the file, it'll - // eventually get pushed out of the caches as the user opens other files. - auto preloaded_ptr = preloaded_sessions_.TryTake(filename); - LOG_IF_S(INFO, !!preloaded_ptr) - << "Dropped preloaded-based code completion session for " << filename; - auto completion_ptr = completion_sessions_.TryTake(filename); - LOG_IF_S(INFO, !!completion_ptr) - << "Dropped completion-based code completion session for " << filename; - - // We should never have both a preloaded and completion session. - assert((preloaded_ptr && completion_ptr) == false); -} - -bool ClangCompleteManager::EnsureCompletionOrCreatePreloadSession( - const std::string &filename) { - std::lock_guard lock(sessions_lock_); - - // Check for an existing CompletionSession. - if (preloaded_sessions_.TryGet(filename) || - completion_sessions_.TryGet(filename)) { - return false; +void CompletionManager::DiagnosticsUpdate(const std::string &path, + int debounce) { + static GroupMatch match(g_config->diagnostics.whitelist, + g_config->diagnostics.blacklist); + if (!match.IsMatch(path)) + return; + int64_t now = chrono::duration_cast( + chrono::high_resolution_clock::now().time_since_epoch()) + .count(); + bool flag = false; + { + std::lock_guard lock(diag_mutex); + int64_t &next = next_diag[path]; + auto &d = g_config->diagnostics; + if (next <= now || + now - next > std::max(d.onChange, std::max(d.onChange, d.onSave))) { + next = now + debounce; + flag = true; + } } + if (flag) + diagnostic_request_.PushBack({path, now + debounce, debounce}, false); +} + +void CompletionManager::NotifyView(const std::string &path) { + // Only reparse the file if we create a new CompletionSession. + if (EnsureCompletionOrCreatePreloadSession(path)) + preload_requests_.PushBack(PreloadRequest{path}, true); +} + +void CompletionManager::NotifySave(const std::string &filename) { + EnsureCompletionOrCreatePreloadSession(filename); + preload_requests_.PushBack(PreloadRequest{filename}, true); +} + +void CompletionManager::OnClose(const std::string &filename) { + std::lock_guard lock(sessions_lock_); + preloads.TryTake(filename); + sessions.TryTake(filename); +} + +bool CompletionManager::EnsureCompletionOrCreatePreloadSession( + const std::string &path) { + std::lock_guard lock(sessions_lock_); + if (preloads.TryGet(path) || sessions.TryGet(path)) + return false; // No CompletionSession, create new one. - auto session = std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_); - preloaded_sessions_.Insert(session->file.filename, session); + auto session = std::make_shared( + project_->FindEntry(path, false), working_files_, PCH); + if (session->file.filename != path) { + session->inferred = true; + session->file.filename = path; + } + preloads.Insert(path, session); + LOG_S(INFO) << "create preload session for " << path; return true; } -std::shared_ptr -ClangCompleteManager::TryGetSession(const std::string &filename, - bool mark_as_completion, - bool create_if_needed) { +std::shared_ptr +CompletionManager::TryGetSession(const std::string &path, bool preload, + bool *is_open) { std::lock_guard lock(sessions_lock_); + std::shared_ptr session = preloads.TryGet(path); - // Try to find a preloaded session. - std::shared_ptr preloaded_session = - preloaded_sessions_.TryGet(filename); - - if (preloaded_session) { - // If this request is for a completion, we should move it to - // |completion_sessions|. - if (mark_as_completion) { - preloaded_sessions_.TryTake(filename); - completion_sessions_.Insert(filename, preloaded_session); + if (session) { + if (!preload) { + preloads.TryTake(path); + sessions.Insert(path, session); + if (is_open) + *is_open = true; } - - return preloaded_session; + return session; } - // Try to find a completion session. If none create one. - std::shared_ptr completion_session = - completion_sessions_.TryGet(filename); - if (!completion_session && create_if_needed) { - completion_session = std::make_shared( - project_->FindCompilationEntryForFile(filename), working_files_); - completion_sessions_.Insert(filename, completion_session); + session = sessions.TryGet(path); + if (!session && !preload) { + session = std::make_shared( + project_->FindEntry(path, false), working_files_, PCH); + sessions.Insert(path, session); + LOG_S(INFO) << "create session for " << path; + if (is_open) + *is_open = true; } - return completion_session; + return session; } -void ClangCompleteManager::FlushSession(const std::string &filename) { - std::lock_guard lock(sessions_lock_); - - preloaded_sessions_.TryTake(filename); - completion_sessions_.TryTake(filename); -} - -void ClangCompleteManager::FlushAllSessions() { +void CompletionManager::FlushAllSessions() { LOG_S(INFO) << "flush all clang complete sessions"; std::lock_guard lock(sessions_lock_); - preloaded_sessions_.Clear(); - completion_sessions_.Clear(); -} - -void CodeCompleteCache::WithLock(std::function action) { - std::lock_guard lock(mutex_); - action(); -} - -bool CodeCompleteCache::IsCacheValid(lsTextDocumentPositionParams position) { - std::lock_guard lock(mutex_); - return cached_path_ == position.textDocument.uri.GetPath() && - cached_completion_position_ == position.position; + preloads.Clear(); + sessions.Clear(); } diff --git a/src/clang_complete.h b/src/clang_complete.hh similarity index 54% rename from src/clang_complete.h rename to src/clang_complete.hh index d3f03492..7020ab4d 100644 --- a/src/clang_complete.h +++ b/src/clang_complete.hh @@ -15,7 +15,7 @@ limitations under the License. #pragma once -#include "clang_tu.h" +#include "clang_tu.hh" #include "lru_cache.h" #include "lsp_completion.h" #include "lsp_diagnostic.h" @@ -23,97 +23,119 @@ limitations under the License. #include "threaded_queue.h" #include "working_files.h" +#include +#include +#include + #include #include #include #include -struct CompletionSession - : public std::enable_shared_from_this { - // Translation unit for clang. - struct Tu { - // When |tu| was last parsed. - std::optional> - last_parsed_at; - // Acquired when |tu| is being used. - std::mutex lock; - std::unique_ptr tu; - }; - - Project::Entry file; - WorkingFiles *working_files; - - Tu completion; - Tu diagnostics; - - CompletionSession(const Project::Entry &file, WorkingFiles *wfiles) - : file(file), working_files(wfiles) {} +namespace ccls { +struct DiagBase { + Range range; + std::string message; + std::string file; + clang::DiagnosticsEngine::Level level = clang::DiagnosticsEngine::Note; + unsigned category; + bool concerned = false; +}; +struct Note : DiagBase {}; +struct Diag : DiagBase { + std::vector notes; + std::vector edits; }; -struct ClangCompleteManager { +struct PreambleData { + PreambleData(clang::PrecompiledPreamble P, std::vector diags) + : Preamble(std::move(P)), diags(std::move(diags)) {} + clang::PrecompiledPreamble Preamble; + std::vector diags; +}; + +struct CompletionSession + : public std::enable_shared_from_this { + std::mutex mutex; + std::shared_ptr preamble; + + Project::Entry file; + WorkingFiles *wfiles; + bool inferred = false; + + // TODO share + llvm::IntrusiveRefCntPtr FS = + clang::vfs::getRealFileSystem(); + std::shared_ptr PCH; + + CompletionSession(const Project::Entry &file, WorkingFiles *wfiles, + std::shared_ptr PCH) + : file(file), wfiles(wfiles), PCH(PCH) {} + + std::shared_ptr GetPreamble(); + void BuildPreamble(clang::CompilerInvocation &CI, const std::string &main); +}; +} + +struct CompletionManager { using OnDiagnostic = std::function diagnostics)>; - using OnComplete = std::function &results, bool is_cached_result)>; + // If OptConsumer is nullptr, the request has been cancelled. + using OnComplete = + std::function; using OnDropped = std::function; struct PreloadRequest { - PreloadRequest(const std::string &path) - : request_time(std::chrono::high_resolution_clock::now()), path(path) {} - - std::chrono::time_point request_time; std::string path; }; struct CompletionRequest { CompletionRequest(const lsRequestId &id, const lsTextDocumentIdentifier &document, - const lsPosition &position, const OnComplete &on_complete) + const lsPosition &position, + std::unique_ptr Consumer, + clang::CodeCompleteOptions CCOpts, + const OnComplete &on_complete) : id(id), document(document), position(position), + Consumer(std::move(Consumer)), CCOpts(CCOpts), on_complete(on_complete) {} lsRequestId id; lsTextDocumentIdentifier document; lsPosition position; + std::unique_ptr Consumer; + clang::CodeCompleteOptions CCOpts; OnComplete on_complete; }; struct DiagnosticRequest { - lsTextDocumentIdentifier document; + std::string path; + int64_t wait_until; + int64_t debounce; }; - ClangCompleteManager(Project *project, WorkingFiles *working_files, - OnDiagnostic on_diagnostic, OnDropped on_dropped); + CompletionManager(Project *project, WorkingFiles *working_files, + OnDiagnostic on_diagnostic, OnDropped on_dropped); - // Start a code completion at the given location. |on_complete| will run when - // completion results are available. |on_complete| may run on any thread. - void CodeComplete(const lsRequestId &request_id, - const lsTextDocumentPositionParams &completion_location, - const OnComplete &on_complete); // Request a diagnostics update. - void DiagnosticsUpdate(const lsTextDocumentIdentifier &document); + void DiagnosticsUpdate(const std::string &path, int debounce); // Notify the completion manager that |filename| has been viewed and we // should begin preloading completion data. - void NotifyView(const std::string &filename); - // Notify the completion manager that |filename| has been edited. - void NotifyEdit(const std::string &filename); + void NotifyView(const std::string &path); // Notify the completion manager that |filename| has been saved. This // triggers a reparse. - void NotifySave(const std::string &filename); + void NotifySave(const std::string &path); // Notify the completion manager that |filename| has been closed. Any existing // completion session will be dropped. - void NotifyClose(const std::string &filename); + void OnClose(const std::string &path); // Ensures there is a completion or preloaded session. Returns true if a new // session was created. - bool EnsureCompletionOrCreatePreloadSession(const std::string &filename); + bool EnsureCompletionOrCreatePreloadSession(const std::string &path); // Tries to find an edit session for |filename|. This will move the session // from view to edit. - std::shared_ptr TryGetSession(const std::string &filename, - bool mark_as_completion, - bool create_if_needed); + std::shared_ptr + TryGetSession(const std::string &path, bool preload, bool *is_open = nullptr); - // Flushes all saved sessions with the supplied filename - void FlushSession(const std::string &filename); // Flushes all saved sessions void FlushAllSessions(void); @@ -127,37 +149,50 @@ struct ClangCompleteManager { OnDiagnostic on_diagnostic_; OnDropped on_dropped_; - using LruSessionCache = LruCache; + using LruSessionCache = LruCache; // CompletionSession instances which are preloaded, ie, files which the user // has viewed but not requested code completion for. - LruSessionCache preloaded_sessions_; + LruSessionCache preloads; // CompletionSession instances which the user has actually performed // completion on. This is more rare so these instances tend to stay alive // much longer than the ones in |preloaded_sessions_|. - LruSessionCache completion_sessions_; + LruSessionCache sessions; // Mutex which protects |view_sessions_| and |edit_sessions_|. std::mutex sessions_lock_; + std::mutex diag_mutex; + std::unordered_map next_diag; + // Request a code completion at the given location. ThreadedQueue> completion_request_; ThreadedQueue diagnostic_request_; // Parse requests. The path may already be parsed, in which case it should be // reparsed. ThreadedQueue preload_requests_; + + std::shared_ptr PCH; }; // Cached completion information, so we can give fast completion results when // the user erases a character. vscode will resend the completion request if // that happens. -struct CodeCompleteCache { +template +struct CompleteConsumerCache { // NOTE: Make sure to access these variables under |WithLock|. - std::optional cached_path_; - std::optional cached_completion_position_; - std::vector cached_results_; + std::optional path; + std::optional position; + T result; - std::mutex mutex_; + std::mutex mutex; - void WithLock(std::function action); - bool IsCacheValid(lsTextDocumentPositionParams position); + void WithLock(std::function action) { + std::lock_guard lock(mutex); + action(); + } + bool IsCacheValid(const lsTextDocumentPositionParams ¶ms) { + std::lock_guard lock(mutex); + return path == params.textDocument.uri.GetPath() && + position == params.position; + } }; diff --git a/src/clang_tu.cc b/src/clang_tu.cc index 28984f19..f147b4c2 100644 --- a/src/clang_tu.cc +++ b/src/clang_tu.cc @@ -13,19 +13,32 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_tu.h" +#include "clang_tu.hh" -#include "clang_utils.h" -#include "log.hh" +#include "config.h" #include "platform.h" -#include "utils.h" -#include "working_files.h" -#include +#include +#include +#include + +#include + using namespace clang; -#include -#include +std::string PathFromFileEntry(const FileEntry &file) { + StringRef Name = file.tryGetRealPathName(); + if (Name.empty()) + Name = file.getName(); + std::string ret = NormalizePath(Name); + // Resolve /usr/include/c++/7.3.0 symlink. + if (!StartsWith(ret, g_config->projectRoot)) { + SmallString<256> dest; + llvm::sys::fs::real_path(ret, dest); + ret = llvm::sys::path::convert_to_slash(dest.str()); + } + return ret; +} Range FromCharSourceRange(const SourceManager &SM, const LangOptions &LangOpts, CharSourceRange R, @@ -68,71 +81,166 @@ Range FromTokenRange(const SourceManager &SM, const LangOptions &LangOpts, UniqueID); } -std::vector -GetRemapped(const WorkingFiles::Snapshot &snapshot) { - std::vector Remapped; - for (auto &file : snapshot.files) { - std::unique_ptr MB = - llvm::MemoryBuffer::getMemBufferCopy(file.content, file.filename); - Remapped.emplace_back(file.filename, MB.release()); - } - return Remapped; -} - -std::unique_ptr ClangTranslationUnit::Create( - const std::string &filepath, const std::vector &args, - const WorkingFiles::Snapshot &snapshot, bool diagnostic) { - std::vector Args; - for (auto &arg : args) - Args.push_back(arg.c_str()); - Args.push_back("-fallow-editor-placeholders"); - if (!diagnostic) - Args.push_back("-fno-spell-checking"); - - auto ret = std::make_unique(); +std::unique_ptr +BuildCompilerInvocation(std::vector args, + IntrusiveRefCntPtr VFS) { + std::string save = "-resource-dir=" + g_config->clang.resourceDir; + args.push_back(save.c_str()); IntrusiveRefCntPtr Diags( CompilerInstance::createDiagnostics(new DiagnosticOptions)); - std::vector Remapped = GetRemapped(snapshot); - - ret->PCHCO = std::make_shared(); - std::unique_ptr ErrUnit, Unit; - llvm::CrashRecoveryContext CRC; - auto parse = [&]() { - Unit.reset(ASTUnit::LoadFromCommandLine( - Args.data(), Args.data() + Args.size(), - /*PCHContainerOpts=*/ret->PCHCO, Diags, - /*ResourceFilePath=*/g_config->clang.resourceDir, - /*OnlyLocalDecls=*/false, - /*CaptureDiagnostics=*/diagnostic, Remapped, - /*RemappedFilesKeepOriginalName=*/true, 1, - diagnostic ? TU_Complete : TU_Prefix, - /*CacheCodeCompletionResults=*/true, g_config->index.comments, - /*AllowPCHWithCompilerErrors=*/true, -#if LLVM_VERSION_MAJOR >= 7 - SkipFunctionBodiesScope::None, -#else - false, -#endif - /*SingleFileParse=*/false, - /*UserFilesAreVolatile=*/true, false, - ret->PCHCO->getRawReader().getFormat(), &ErrUnit)); - }; - if (!CRC.RunSafely(parse)) { - LOG_S(ERROR) << "clang crashed for " << filepath << "\n" - << StringJoin(args, " ") + " -fsyntax-only"; - return {}; + std::unique_ptr CI = + createInvocationFromCommandLine(args, Diags, VFS); + if (CI) { + CI->getDiagnosticOpts().IgnoreWarnings = true; + CI->getFrontendOpts().DisableFree = false; + CI->getLangOpts()->SpellChecking = false; } - if (!Unit && !ErrUnit) - return {}; - - ret->Unit = std::move(Unit); - return ret; + return CI; } -int ClangTranslationUnit::Reparse(llvm::CrashRecoveryContext &CRC, - const WorkingFiles::Snapshot &snapshot) { - int ret = 1; - (void)CRC.RunSafely( - [&]() { ret = Unit->Reparse(PCHCO, GetRemapped(snapshot)); }); - return ret; +// clang::BuiltinType::getName without PrintingPolicy +const char *ClangBuiltinTypeName(int kind) { + switch (BuiltinType::Kind(kind)) { + case BuiltinType::Void: + return "void"; + case BuiltinType::Bool: + return "bool"; + case BuiltinType::Char_S: + return "char"; + case BuiltinType::Char_U: + return "char"; + case BuiltinType::SChar: + return "signed char"; + case BuiltinType::Short: + return "short"; + case BuiltinType::Int: + return "int"; + case BuiltinType::Long: + return "long"; + case BuiltinType::LongLong: + return "long long"; + case BuiltinType::Int128: + return "__int128"; + case BuiltinType::UChar: + return "unsigned char"; + case BuiltinType::UShort: + return "unsigned short"; + case BuiltinType::UInt: + return "unsigned int"; + case BuiltinType::ULong: + return "unsigned long"; + case BuiltinType::ULongLong: + return "unsigned long long"; + case BuiltinType::UInt128: + return "unsigned __int128"; + case BuiltinType::Half: + return "__fp16"; + case BuiltinType::Float: + return "float"; + case BuiltinType::Double: + return "double"; + case BuiltinType::LongDouble: + return "long double"; +#if LLVM_VERSION_MAJOR >= 7 + case BuiltinType::ShortAccum: + return "short _Accum"; + case BuiltinType::Accum: + return "_Accum"; + case BuiltinType::LongAccum: + return "long _Accum"; + case BuiltinType::UShortAccum: + return "unsigned short _Accum"; + case BuiltinType::UAccum: + return "unsigned _Accum"; + case BuiltinType::ULongAccum: + return "unsigned long _Accum"; + case BuiltinType::BuiltinType::ShortFract: + return "short _Fract"; + case BuiltinType::BuiltinType::Fract: + return "_Fract"; + case BuiltinType::BuiltinType::LongFract: + return "long _Fract"; + case BuiltinType::BuiltinType::UShortFract: + return "unsigned short _Fract"; + case BuiltinType::BuiltinType::UFract: + return "unsigned _Fract"; + case BuiltinType::BuiltinType::ULongFract: + return "unsigned long _Fract"; + case BuiltinType::BuiltinType::SatShortAccum: + return "_Sat short _Accum"; + case BuiltinType::BuiltinType::SatAccum: + return "_Sat _Accum"; + case BuiltinType::BuiltinType::SatLongAccum: + return "_Sat long _Accum"; + case BuiltinType::BuiltinType::SatUShortAccum: + return "_Sat unsigned short _Accum"; + case BuiltinType::BuiltinType::SatUAccum: + return "_Sat unsigned _Accum"; + case BuiltinType::BuiltinType::SatULongAccum: + return "_Sat unsigned long _Accum"; + case BuiltinType::BuiltinType::SatShortFract: + return "_Sat short _Fract"; + case BuiltinType::BuiltinType::SatFract: + return "_Sat _Fract"; + case BuiltinType::BuiltinType::SatLongFract: + return "_Sat long _Fract"; + case BuiltinType::BuiltinType::SatUShortFract: + return "_Sat unsigned short _Fract"; + case BuiltinType::BuiltinType::SatUFract: + return "_Sat unsigned _Fract"; + case BuiltinType::BuiltinType::SatULongFract: + return "_Sat unsigned long _Fract"; +#endif + case BuiltinType::Float16: + return "_Float16"; + case BuiltinType::Float128: + return "__float128"; + case BuiltinType::WChar_S: + case BuiltinType::WChar_U: + return "wchar_t"; +#if LLVM_VERSION_MAJOR >= 7 + case BuiltinType::Char8: + return "char8_t"; +#endif + case BuiltinType::Char16: + return "char16_t"; + case BuiltinType::Char32: + return "char32_t"; + case BuiltinType::NullPtr: + return "nullptr_t"; + case BuiltinType::Overload: + return ""; + case BuiltinType::BoundMember: + return ""; + case BuiltinType::PseudoObject: + return ""; + case BuiltinType::Dependent: + return ""; + case BuiltinType::UnknownAny: + return ""; + case BuiltinType::ARCUnbridgedCast: + return ""; + case BuiltinType::BuiltinFn: + return ""; + case BuiltinType::ObjCId: + return "id"; + case BuiltinType::ObjCClass: + return "Class"; + case BuiltinType::ObjCSel: + return "SEL"; + case BuiltinType::OCLSampler: + return "sampler_t"; + case BuiltinType::OCLEvent: + return "event_t"; + case BuiltinType::OCLClkEvent: + return "clk_event_t"; + case BuiltinType::OCLQueue: + return "queue_t"; + case BuiltinType::OCLReserveID: + return "reserve_id_t"; + case BuiltinType::OMPArraySection: + return ""; + default: + return ""; + } } diff --git a/src/clang_tu.h b/src/clang_tu.hh similarity index 66% rename from src/clang_tu.h rename to src/clang_tu.hh index fa7f4f7b..96325466 100644 --- a/src/clang_tu.h +++ b/src/clang_tu.hh @@ -14,20 +14,15 @@ limitations under the License. ==============================================================================*/ #pragma once + #include "position.h" -#include "working_files.h" -#include +#include +#include +#include #include -#include -#include -#include -#include -#include - -std::vector -GetRemapped(const WorkingFiles::Snapshot &snapshot); +std::string PathFromFileEntry(const clang::FileEntry &file); Range FromCharSourceRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts, @@ -42,14 +37,8 @@ Range FromTokenRange(const clang::SourceManager &SM, const clang::LangOptions &LangOpts, clang::SourceRange R, llvm::sys::fs::UniqueID *UniqueID = nullptr); -struct ClangTranslationUnit { - static std::unique_ptr - Create(const std::string &filepath, const std::vector &args, - const WorkingFiles::Snapshot &snapshot, bool diagnostic); +std::unique_ptr +BuildCompilerInvocation(std::vector args, + llvm::IntrusiveRefCntPtr VFS); - int Reparse(llvm::CrashRecoveryContext &CRC, - const WorkingFiles::Snapshot &snapshot); - - std::shared_ptr PCHCO; - std::unique_ptr Unit; -}; +const char *ClangBuiltinTypeName(int); diff --git a/src/clang_utils.cc b/src/clang_utils.cc deleted file mode 100644 index 6a92b73b..00000000 --- a/src/clang_utils.cc +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_utils.h" - -#include "config.h" -#include "filesystem.hh" -#include "platform.h" -#include "utils.h" - -#include -#include -using namespace clang; -using namespace llvm; - -std::string FileName(const FileEntry &file) { - StringRef Name = file.tryGetRealPathName(); - if (Name.empty()) - Name = file.getName(); - std::string ret = NormalizePath(Name); - // Resolve /usr/include/c++/7.3.0 symlink. - if (!StartsWith(ret, g_config->projectRoot)) { - SmallString<256> dest; - sys::fs::real_path(ret, dest); - ret = dest.str(); - } - return ret; -} - -// clang::BuiltinType::getName without PrintingPolicy -const char *ClangBuiltinTypeName(int kind) { - switch (BuiltinType::Kind(kind)) { - case BuiltinType::Void: - return "void"; - case BuiltinType::Bool: - return "bool"; - case BuiltinType::Char_S: - return "char"; - case BuiltinType::Char_U: - return "char"; - case BuiltinType::SChar: - return "signed char"; - case BuiltinType::Short: - return "short"; - case BuiltinType::Int: - return "int"; - case BuiltinType::Long: - return "long"; - case BuiltinType::LongLong: - return "long long"; - case BuiltinType::Int128: - return "__int128"; - case BuiltinType::UChar: - return "unsigned char"; - case BuiltinType::UShort: - return "unsigned short"; - case BuiltinType::UInt: - return "unsigned int"; - case BuiltinType::ULong: - return "unsigned long"; - case BuiltinType::ULongLong: - return "unsigned long long"; - case BuiltinType::UInt128: - return "unsigned __int128"; - case BuiltinType::Half: - return "__fp16"; - case BuiltinType::Float: - return "float"; - case BuiltinType::Double: - return "double"; - case BuiltinType::LongDouble: - return "long double"; -#if LLVM_VERSION_MAJOR >= 7 - case BuiltinType::ShortAccum: - return "short _Accum"; - case BuiltinType::Accum: - return "_Accum"; - case BuiltinType::LongAccum: - return "long _Accum"; - case BuiltinType::UShortAccum: - return "unsigned short _Accum"; - case BuiltinType::UAccum: - return "unsigned _Accum"; - case BuiltinType::ULongAccum: - return "unsigned long _Accum"; - case BuiltinType::BuiltinType::ShortFract: - return "short _Fract"; - case BuiltinType::BuiltinType::Fract: - return "_Fract"; - case BuiltinType::BuiltinType::LongFract: - return "long _Fract"; - case BuiltinType::BuiltinType::UShortFract: - return "unsigned short _Fract"; - case BuiltinType::BuiltinType::UFract: - return "unsigned _Fract"; - case BuiltinType::BuiltinType::ULongFract: - return "unsigned long _Fract"; - case BuiltinType::BuiltinType::SatShortAccum: - return "_Sat short _Accum"; - case BuiltinType::BuiltinType::SatAccum: - return "_Sat _Accum"; - case BuiltinType::BuiltinType::SatLongAccum: - return "_Sat long _Accum"; - case BuiltinType::BuiltinType::SatUShortAccum: - return "_Sat unsigned short _Accum"; - case BuiltinType::BuiltinType::SatUAccum: - return "_Sat unsigned _Accum"; - case BuiltinType::BuiltinType::SatULongAccum: - return "_Sat unsigned long _Accum"; - case BuiltinType::BuiltinType::SatShortFract: - return "_Sat short _Fract"; - case BuiltinType::BuiltinType::SatFract: - return "_Sat _Fract"; - case BuiltinType::BuiltinType::SatLongFract: - return "_Sat long _Fract"; - case BuiltinType::BuiltinType::SatUShortFract: - return "_Sat unsigned short _Fract"; - case BuiltinType::BuiltinType::SatUFract: - return "_Sat unsigned _Fract"; - case BuiltinType::BuiltinType::SatULongFract: - return "_Sat unsigned long _Fract"; -#endif - case BuiltinType::Float16: - return "_Float16"; - case BuiltinType::Float128: - return "__float128"; - case BuiltinType::WChar_S: - case BuiltinType::WChar_U: - return "wchar_t"; -#if LLVM_VERSION_MAJOR >= 7 - case BuiltinType::Char8: - return "char8_t"; -#endif - case BuiltinType::Char16: - return "char16_t"; - case BuiltinType::Char32: - return "char32_t"; - case BuiltinType::NullPtr: - return "nullptr_t"; - case BuiltinType::Overload: - return ""; - case BuiltinType::BoundMember: - return ""; - case BuiltinType::PseudoObject: - return ""; - case BuiltinType::Dependent: - return ""; - case BuiltinType::UnknownAny: - return ""; - case BuiltinType::ARCUnbridgedCast: - return ""; - case BuiltinType::BuiltinFn: - return ""; - case BuiltinType::ObjCId: - return "id"; - case BuiltinType::ObjCClass: - return "Class"; - case BuiltinType::ObjCSel: - return "SEL"; - case BuiltinType::OCLSampler: - return "sampler_t"; - case BuiltinType::OCLEvent: - return "event_t"; - case BuiltinType::OCLClkEvent: - return "clk_event_t"; - case BuiltinType::OCLQueue: - return "queue_t"; - case BuiltinType::OCLReserveID: - return "reserve_id_t"; - case BuiltinType::OMPArraySection: - return ""; - default: - return ""; - } -} diff --git a/src/clang_utils.h b/src/clang_utils.h deleted file mode 100644 index 769412a9..00000000 --- a/src/clang_utils.h +++ /dev/null @@ -1,25 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#pragma once - -#include - -#include - -// Returns the absolute path to |file|. -std::string FileName(const clang::FileEntry &file); - -const char *ClangBuiltinTypeName(int); diff --git a/src/config.cc b/src/config.cc index bd0ecc2b..0d4b9039 100644 --- a/src/config.cc +++ b/src/config.cc @@ -16,4 +16,16 @@ limitations under the License. #include "config.h" Config *g_config; -thread_local int g_thread_id; + +namespace ccls { +void DoPathMapping(std::string &arg) { + for (const std::string &mapping : g_config->clang.pathMappings) { + auto colon = mapping.find(':'); + if (colon != std::string::npos) { + auto p = arg.find(mapping.substr(0, colon)); + if (p != std::string::npos) + arg.replace(p, colon, mapping.substr(colon + 1)); + } + } +} +} diff --git a/src/config.h b/src/config.h index ab5eb5eb..8889f94b 100644 --- a/src/config.h +++ b/src/config.h @@ -21,14 +21,7 @@ limitations under the License. /* The language client plugin needs to send initialization options in the -`initialize` request to the ccls language server. The only required option is -`cacheDirectory`, which is where index files will be stored. - - { - "initializationOptions": { - "cacheDirectory": "/tmp/ccls" - } - } +`initialize` request to the ccls language server. If necessary, the command line option --init can be used to override initialization options specified by the client. For example, in shell syntax: @@ -47,6 +40,7 @@ struct Config { std::string compilationDatabaseDirectory; // Cache directory for indexed files, either absolute or relative to the // project root. + // If empty, cache will be stored in memory. std::string cacheDirectory = ".ccls-cache"; // Cache serialization format. // @@ -54,14 +48,31 @@ struct Config { // printed with jq. // // "binary" uses a compact binary serialization format. - // It is not schema-aware and you need to re-index whenever a struct + // It is not schema-aware and you need to re-index whenever an internal struct // member has changed. SerializeFormat cacheFormat = SerializeFormat::Binary; struct Clang { + // Arguments that should be excluded, e.g. ["-fopenmp", "-Wall"] + // + // e.g. If your project is built by GCC and has an option thag clang does not understand. + std::vector excludeArgs; + // Additional arguments to pass to clang. std::vector extraArgs; + // Translate absolute paths in compile_commands.json entries, .ccls options + // and cache files. This allows to reuse cache files built otherwhere if the + // source paths are different. + // + // This is a list of colon-separated strings, e.g. ["/container:/host"] + // + // An entry of "clang -I /container/include /container/a.cc" will be + // translated to "clang -I /host/include /host/a.cc". This is simple string + // replacement, so "clang /prefix/container/a.cc" will become "clang + // /prefix/host/a.cc". + std::vector pathMappings; + // Value to use for clang -resource-dir if not specified. // // This option defaults to clang -print-resource-dir and should not be @@ -70,8 +81,10 @@ struct Config { } clang; struct ClientCapability { + // TextDocumentClientCapabilities.documentSymbol.hierarchicalDocumentSymbolSupport + bool hierarchicalDocumentSymbolSupport = true; // TextDocumentClientCapabilities.completion.completionItem.snippetSupport - bool snippetSupport = false; + bool snippetSupport = true; } client; struct CodeLens { @@ -93,16 +106,7 @@ struct Config { // When this option is enabled, the completion item label is very detailed, // it shows the full signature of the candidate. // The detail just contains the completion item parent context. - // Also, in this mode, functions with default arguments, - // generates one more item per default argument - // so that the right function call can be selected. - // That is, you get something like: - // "int foo()" "Foo" - // "void bar()" "Foo" - // "void bar(int i = 0)" "Foo" - // Be wary, this is quickly quite verbose, - // items can end up truncated by the UIs. - bool detailedLabel = false; + bool detailedLabel = true; // On large projects, completion can take a long time. By default if ccls // receives multiple completion requests while completion is still running @@ -110,6 +114,15 @@ struct Config { // completion requests will be serviced. bool dropOldRequests = true; + // Functions with default arguments, generate one more item per default + // argument. That is, you get something like: + // "int foo()" "Foo" + // "void bar()" "Foo" + // "void bar(int i = 0)" "Foo" + // Be wary, this is quickly quite verbose, + // items can end up truncated by the UIs. + bool duplicateOptional = true; + // If true, filter and sort completion response. ccls filters and sorts // completions to try to be nicer to clients that can't handle big numbers // of completion candidates. This behaviour can be disabled by specifying @@ -117,25 +130,27 @@ struct Config { // that implement their own filtering and sorting logic. bool filterAndSort = true; - // Regex patterns to match include completion candidates against. They - // receive the absolute file path. - // - // For example, to hide all files in a /CACHE/ folder, use ".*/CACHE/.*" - std::vector includeBlacklist; + struct Include { + // Regex patterns to match include completion candidates against. They + // receive the absolute file path. + // + // For example, to hide all files in a /CACHE/ folder, use ".*/CACHE/.*" + std::vector blacklist; - // Maximum path length to show in completion results. Paths longer than this - // will be elided with ".." put at the front. Set to 0 or a negative number - // to disable eliding. - int includeMaxPathSize = 30; + // Maximum path length to show in completion results. Paths longer than + // this will be elided with ".." put at the front. Set to 0 or a negative + // number to disable eliding. + int maxPathSize = 30; - // Whitelist that file paths will be tested against. If a file path does not - // end in one of these values, it will not be considered for - // auto-completion. An example value is { ".h", ".hpp" } - // - // This is significantly faster than using a regex. - std::vector includeSuffixWhitelist = {".h", ".hpp", ".hh"}; + // Whitelist that file paths will be tested against. If a file path does + // not end in one of these values, it will not be considered for + // auto-completion. An example value is { ".h", ".hpp" } + // + // This is significantly faster than using a regex. + std::vector suffixWhitelist = {".h", ".hpp", ".hh", ".inc"}; - std::vector includeWhitelist; + std::vector whitelist; + } include; } completion; struct Diagnostics { @@ -143,23 +158,29 @@ struct Config { // blacklisted files. std::vector blacklist; - // How often should ccls publish diagnostics in completion? - // -1: never - // 0: as often as possible - // xxx: at most every xxx milliseconds - int frequencyMs = 0; + // Time to wait before computing diagnostics for textDocument/didChange. + // -1: disable diagnostics on change + // 0: immediately + // positive (e.g. 500): wait for 500 milliseconds. didChange requests in + // this period of time will only cause one computation. + int onChange = 1000; - // If true, diagnostics from a full document parse will be reported. - bool onParse = true; + // Time to wait before computing diagnostics for textDocument/didOpen. + int onOpen = 0; - // If true, diagnostics from typing will be reported. - bool onType = true; + // Time to wait before computing diagnostics for textDocument/didSave. + int onSave = 0; + + bool spellChecking = true; std::vector whitelist; } diagnostics; // Semantic highlighting struct Highlight { + // Disable semantic highlighting for files larger than the size. + int64_t largeFileSize = 2 * 1024 * 1024; + // true: LSP line/character; false: position bool lsRanges = false; @@ -171,14 +192,6 @@ struct Config { } highlight; struct Index { - // Attempt to convert calls of make* functions to constructors based on - // hueristics. - // - // For example, this will show constructor calls for std::make_unique - // invocations. Specifically, ccls will try to attribute a ctor call - // whenever the function name starts with make (ignoring case). - bool attributeMakeCallsToCtor = true; - // If a translation unit's absolute path matches any EMCAScript regex in the // whitelist, or does not match any regex in the blacklist, it will be // indexed. To only index files in the whitelist, add ".*" to the blacklist. @@ -193,27 +206,35 @@ struct Config { // - https://github.com/autozimu/LanguageClient-neovim/issues/224 int comments = 2; - // If false, the indexer will be disabled. - bool enabled = true; + // By default, all project entries will be indexed on initialization. Use + // these two options to exclude some. They can still be indexed after you + // open them. + std::vector initialBlacklist; + std::vector initialWhitelist; + + // If not 0, a file will be indexed in each tranlation unit that includes it. + int multiVersion = 0; + + // If multiVersion != 0, files that match blacklist but not whitelist will + // still only be indexed for one version. + std::vector multiVersionBlacklist; + std::vector multiVersionWhitelist; // Allow indexing on textDocument/didChange. // May be too slow for big projects, so it is off by default. - bool onDidChange = false; - - // Whether to reparse a file if write times of its dependencies have - // changed. The file will always be reparsed if its own write time changes. - // 0: no, 1: only after initial load of project, 2: yes - int reparseForDependency = 2; + bool onChange = false; // Number of indexer threads. If 0, 80% of cores are used. int threads = 0; + // Whether to reparse a file if write times of its dependencies have + // changed. The file will always be reparsed if its own write time changes. + // 0: no, 1: only during initial load of project, 2: yes + int trackDependency = 2; + std::vector whitelist; } index; - // Disable semantic highlighting for files larger than the size. - int64_t largeFileSize = 2 * 1024 * 1024; - struct WorkspaceSymbol { int caseSensitivity = 1; // Maximum workspace search results. @@ -231,26 +252,32 @@ struct Config { int maxNum = 2000; } xref; }; -MAKE_REFLECT_STRUCT(Config::Clang, extraArgs, resourceDir); -MAKE_REFLECT_STRUCT(Config::ClientCapability, snippetSupport); +MAKE_REFLECT_STRUCT(Config::Clang, excludeArgs, extraArgs, pathMappings, + resourceDir); +MAKE_REFLECT_STRUCT(Config::ClientCapability, hierarchicalDocumentSymbolSupport, + snippetSupport); MAKE_REFLECT_STRUCT(Config::CodeLens, localVariables); -MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, dropOldRequests, - detailedLabel, filterAndSort, includeBlacklist, - includeMaxPathSize, includeSuffixWhitelist, - includeWhitelist); -MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, frequencyMs, onParse, - onType, whitelist) -MAKE_REFLECT_STRUCT(Config::Highlight, lsRanges, blacklist, whitelist) -MAKE_REFLECT_STRUCT(Config::Index, attributeMakeCallsToCtor, blacklist, - comments, enabled, onDidChange, reparseForDependency, - threads, whitelist); +MAKE_REFLECT_STRUCT(Config::Completion::Include, blacklist, maxPathSize, + suffixWhitelist, whitelist); +MAKE_REFLECT_STRUCT(Config::Completion, caseSensitivity, detailedLabel, + dropOldRequests, duplicateOptional, filterAndSort, include); +MAKE_REFLECT_STRUCT(Config::Diagnostics, blacklist, onChange, onOpen, onSave, + spellChecking, whitelist) +MAKE_REFLECT_STRUCT(Config::Highlight, largeFileSize, lsRanges, blacklist, + whitelist) +MAKE_REFLECT_STRUCT(Config::Index, blacklist, comments, initialBlacklist, + initialWhitelist, multiVersion, multiVersionBlacklist, + multiVersionWhitelist, onChange, threads, trackDependency, + whitelist); MAKE_REFLECT_STRUCT(Config::WorkspaceSymbol, caseSensitivity, maxNum, sort); MAKE_REFLECT_STRUCT(Config::Xref, container, maxNum); MAKE_REFLECT_STRUCT(Config, compilationDatabaseCommand, compilationDatabaseDirectory, cacheDirectory, cacheFormat, - clang, client, codeLens, completion, diagnostics, highlight, - index, largeFileSize, workspaceSymbol, xref); + index, workspaceSymbol, xref); extern Config *g_config; -thread_local extern int g_thread_id; + +namespace ccls { +void DoPathMapping(std::string &arg); +} diff --git a/src/file_consumer.cc b/src/file_consumer.cc deleted file mode 100644 index 3542b263..00000000 --- a/src/file_consumer.cc +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "file_consumer.h" - -#include "clang_utils.h" -#include "indexer.h" -#include "log.hh" -#include "platform.h" -#include "utils.h" - -namespace { - -std::optional -GetFileContents(const std::string &path, - std::unordered_map *file_contents) { - auto it = file_contents->find(path); - if (it == file_contents->end()) { - std::optional content = ReadContent(path); - if (content) - (*file_contents)[path] = FileContents(path, *content); - return content; - } - return it->second.content; -} - -} // namespace - -FileContents::FileContents(const std::string &path, const std::string &content) - : path(path), content(content) { - line_offsets_.push_back(0); - for (size_t i = 0; i < content.size(); i++) { - if (content[i] == '\n') - line_offsets_.push_back(i + 1); - } -} - -std::optional FileContents::ToOffset(Position p) const { - if (0 <= p.line && size_t(p.line) < line_offsets_.size()) { - int ret = line_offsets_[p.line] + p.column; - if (size_t(ret) < content.size()) - return ret; - } - return std::nullopt; -} - -std::optional FileContents::ContentsInRange(Range range) const { - std::optional start_offset = ToOffset(range.start), - end_offset = ToOffset(range.end); - if (start_offset && end_offset && *start_offset < *end_offset) - return content.substr(*start_offset, *end_offset - *start_offset); - return std::nullopt; -} - -VFS::State VFS::Get(const std::string &file) { - std::lock_guard lock(mutex); - auto it = state.find(file); - if (it != state.end()) - return it->second; - return {0, 0, 0}; -} - -bool VFS::Mark(const std::string &file, int owner, int stage) { - std::lock_guard lock(mutex); - State &st = state[file]; - if (st.stage < stage) { - st.owner = owner; - st.stage = stage; - return true; - } else - return false; -} - -bool VFS::Stamp(const std::string &file, int64_t ts) { - std::lock_guard lock(mutex); - State &st = state[file]; - if (st.timestamp < ts) { - st.timestamp = ts; - return true; - } else - return false; -} - -void VFS::ResetLocked(const std::string &file) { - State &st = state[file]; - if (st.owner == 0 || st.owner == g_thread_id) - st.stage = 0; -} - -void VFS::Reset(const std::string &file) { - std::lock_guard lock(mutex); - ResetLocked(file); -} - -FileConsumer::FileConsumer(VFS *vfs, const std::string &parse_file) - : vfs_(vfs), parse_file_(parse_file), thread_id_(g_thread_id) {} - -IndexFile *FileConsumer::TryConsumeFile( - const clang::FileEntry &File, - std::unordered_map *file_contents_map) { - auto UniqueID = File.getUniqueID(); - auto it = local_.find(UniqueID); - if (it != local_.end()) - return it->second.get(); - - std::string file_name = FileName(File); - // We did not take the file from global. Cache that we failed so we don't try - // again and return nullptr. - if (!vfs_->Mark(file_name, thread_id_, 2)) { - local_[UniqueID] = nullptr; - return nullptr; - } - - // Read the file contents, if we fail then we cannot index the file. - std::optional contents = - GetFileContents(file_name, file_contents_map); - if (!contents) - return nullptr; - - // Build IndexFile instance. - local_[UniqueID] = - std::make_unique(UniqueID, file_name, *contents); - return local_[UniqueID].get(); -} - -std::vector> FileConsumer::TakeLocalState() { - std::vector> result; - for (auto &entry : local_) { - if (entry.second) - result.push_back(std::move(entry.second)); - } - return result; -} diff --git a/src/file_consumer.h b/src/file_consumer.h deleted file mode 100644 index b0292084..00000000 --- a/src/file_consumer.h +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#pragma once - -#include "position.h" -#include "serializer.h" -#include "utils.h" - -#include - -#include -#include -#include - -struct IndexFile; - -struct FileContents { - FileContents() = default; - FileContents(const std::string &path, const std::string &content); - - std::optional ToOffset(Position p) const; - std::optional ContentsInRange(Range range) const; - - std::string path; - std::string content; - // {0, 1 + position of first newline, 1 + position of second newline, ...} - std::vector line_offsets_; -}; - -struct VFS { - struct State { - int64_t timestamp; - int owner; - int stage; - }; - mutable std::unordered_map state; - mutable std::mutex mutex; - - State Get(const std::string &file); - bool Mark(const std::string &file, int owner, int stage); - bool Stamp(const std::string &file, int64_t ts); - void ResetLocked(const std::string &file); - void Reset(const std::string &file); -}; - -namespace std { -template <> struct hash { - std::size_t operator()(llvm::sys::fs::UniqueID ID) const { - size_t ret = ID.getDevice(); - hash_combine(ret, ID.getFile()); - return ret; - } -}; -} // namespace std - -// FileConsumer is used by the indexer. When it encouters a file, it tries to -// take ownership over it. If the indexer has ownership over a file, it will -// produce an index, otherwise, it will emit nothing for that declarations -// and references coming from that file. -// -// The indexer does this because header files do not have their own translation -// units but we still want to index them. -struct FileConsumer { - FileConsumer(VFS *vfs, const std::string &parse_file); - - // Returns IndexFile for the file or nullptr. |is_first_ownership| is set - // to true iff the function just took ownership over the file. Otherwise it - // is set to false. - // - // note: file_contents is passed as a parameter instead of as a member - // variable since it is large and we do not want to copy it. - IndexFile * - TryConsumeFile(const clang::FileEntry &file, - std::unordered_map *file_contents); - - // Returns and passes ownership of all local state. - std::vector> TakeLocalState(); - -private: - std::unordered_map> - local_; - VFS *vfs_; - std::string parse_file_; - int thread_id_; -}; diff --git a/src/filesystem.cc b/src/filesystem.cc index 74eb836b..613666ad 100644 --- a/src/filesystem.cc +++ b/src/filesystem.cc @@ -59,7 +59,7 @@ void GetFilesInFolder(std::string folder, bool recursive, bool dir_prefix, if (sys::fs::is_regular_file(Status)) { if (!dir_prefix) path = path.substr(folder.size()); - handler(path); + handler(sys::path::convert_to_slash(path)); } else if (recursive && sys::fs::is_directory(Status) && !seen.count(ID = Status.getUniqueID())) { curr.push_back(path); diff --git a/src/fuzzy_match.cc b/src/fuzzy_match.cc index 3d69d925..577f6223 100644 --- a/src/fuzzy_match.cc +++ b/src/fuzzy_match.cc @@ -43,7 +43,7 @@ void CalculateRoles(std::string_view s, int roles[], int *class_set) { if (cur == Other) return None; // U(U)L is Head while U(U)U is Tail - return pre == Other || (cur == Upper && (pre == Lower || suc != Upper)) + return pre == Other || (cur == Upper && (pre == Lower || suc == Lower)) ? Head : Tail; }; diff --git a/src/lsp_code_action.h b/src/hierarchy.hh similarity index 53% rename from src/lsp_code_action.h rename to src/hierarchy.hh index 15ed6be4..c79cbd0d 100644 --- a/src/lsp_code_action.h +++ b/src/hierarchy.hh @@ -17,20 +17,23 @@ limitations under the License. #include "lsp.h" -// codeAction -struct CommandArgs { - lsDocumentUri textDocumentUri; - std::vector edits; -}; -MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(CommandArgs, textDocumentUri, edits); +#include +#include -// codeLens -struct lsCodeLensUserData {}; -MAKE_REFLECT_EMPTY_STRUCT(lsCodeLensUserData); - -struct lsCodeLensCommandArguments { - lsDocumentUri uri; - lsPosition position; - std::vector locations; -}; -MAKE_REFLECT_STRUCT(lsCodeLensCommandArguments, uri, position, locations) +template +void FlattenHierarchy(const Node &root, Out_LocationList &out) { + std::queue q; + for (auto &entry : root.children) + q.push(&entry); + while (q.size()) { + auto *entry = q.front(); + q.pop(); + if (entry->location.uri.raw_uri.size()) + out.result.push_back({entry->location}); + for (auto &entry1 : entry->children) + q.push(&entry1); + } + std::sort(out.result.begin(), out.result.end()); + out.result.erase(std::unique(out.result.begin(), out.result.end()), + out.result.end()); +} diff --git a/src/include_complete.cc b/src/include_complete.cc index 779b04b0..e634e189 100644 --- a/src/include_complete.cc +++ b/src/include_complete.cc @@ -35,13 +35,11 @@ struct CompletionCandidate { }; std::string ElideLongPath(const std::string &path) { - if (g_config->completion.includeMaxPathSize <= 0) + if (g_config->completion.include.maxPathSize <= 0 || + (int)path.size() <= g_config->completion.include.maxPathSize) return path; - if ((int)path.size() <= g_config->completion.includeMaxPathSize) - return path; - - size_t start = path.size() - g_config->completion.includeMaxPathSize; + size_t start = path.size() - g_config->completion.include.maxPathSize; return ".." + path.substr(start + 2); } @@ -113,11 +111,11 @@ void IncludeComplete::Rescan() { absolute_path_to_completion_item.clear(); inserted_paths.clear(); - if (!match_ && (g_config->completion.includeWhitelist.size() || - g_config->completion.includeBlacklist.size())) + if (!match_ && (g_config->completion.include.whitelist.size() || + g_config->completion.include.blacklist.size())) match_ = - std::make_unique(g_config->completion.includeWhitelist, - g_config->completion.includeBlacklist); + std::make_unique(g_config->completion.include.whitelist, + g_config->completion.include.blacklist); is_scanning = true; std::thread([this]() { @@ -156,7 +154,7 @@ void IncludeComplete::InsertCompletionItem(const std::string &absolute_path, } void IncludeComplete::AddFile(const std::string &absolute_path) { - if (!EndsWithAny(absolute_path, g_config->completion.includeSuffixWhitelist)) + if (!EndsWithAny(absolute_path, g_config->completion.include.suffixWhitelist)) return; if (match_ && !match_->IsMatch(absolute_path)) return; @@ -186,7 +184,7 @@ void IncludeComplete::InsertIncludesFromDirectory(std::string directory, directory, true /*recursive*/, false /*add_folder_to_path*/, [&](const std::string &path) { if (!include_cpp && - !EndsWithAny(path, g_config->completion.includeSuffixWhitelist)) + !EndsWithAny(path, g_config->completion.include.suffixWhitelist)) return; if (match_ && !match_->IsMatch(directory + path)) return; diff --git a/src/indexer.cc b/src/indexer.cc index d0893657..ccc5b64f 100644 --- a/src/indexer.cc +++ b/src/indexer.cc @@ -15,15 +15,15 @@ limitations under the License. #include "indexer.h" -#include "clang_tu.h" +#include "clang_complete.hh" +#include "clang_tu.hh" #include "log.hh" +#include "match.h" +#include "pipeline.hh" #include "platform.h" #include "serializer.h" -using ccls::Intern; #include -#include -#include #include #include #include @@ -32,24 +32,31 @@ using ccls::Intern; #include #include #include -#include -using namespace clang; -using llvm::Timer; #include #include -#include #include #include +using namespace ccls; +using namespace clang; + namespace { constexpr int kInitializerMaxLines = 3; +GroupMatch *multiVersionMatcher; + +struct File { + std::string path; + int64_t mtime; + std::string content; + std::unique_ptr db; +}; + struct IndexParam { - std::unordered_map SeenUniqueID; - std::unordered_map file_contents; - std::unordered_map file2write_time; + std::unordered_map UID2File; + std::unordered_map UID2multi; struct DeclInfo { Usr usr; std::string short_name; @@ -57,33 +64,41 @@ struct IndexParam { }; std::unordered_map Decl2Info; - ASTUnit &Unit; + VFS &vfs; ASTContext *Ctx; + IndexParam(VFS &vfs) : vfs(vfs) {} - FileConsumer *file_consumer = nullptr; - - IndexParam(ASTUnit &Unit, FileConsumer *file_consumer) - : Unit(Unit), file_consumer(file_consumer) {} - - IndexFile *ConsumeFile(const FileEntry &File) { - IndexFile *db = file_consumer->TryConsumeFile(File, &file_contents); - + void SeenFile(const FileEntry &File) { // If this is the first time we have seen the file (ignoring if we are // generating an index for it): - auto [it, inserted] = SeenUniqueID.try_emplace(File.getUniqueID()); + auto [it, inserted] = UID2File.try_emplace(File.getUniqueID()); if (inserted) { - std::string file_name = FileName(File); - it->second = file_name; + std::string path = PathFromFileEntry(File); + it->second.path = path; + it->second.mtime = File.getModificationTime(); + if (!it->second.mtime) + if (auto tim = LastWriteTime(path)) + it->second.mtime = *tim; + if (std::optional content = ReadContent(path)) + it->second.content = *content; - // Set modification time. - std::optional write_time = LastWriteTime(file_name); - LOG_IF_S(ERROR, !write_time) - << "failed to fetch write time for " << file_name; - if (write_time) - file2write_time[file_name] = *write_time; + if (!vfs.Stamp(path, it->second.mtime, 1)) + return; + it->second.db = std::make_unique(File.getUniqueID(), path, + it->second.content); } + } - return db; + IndexFile *ConsumeFile(const FileEntry &FE) { + SeenFile(FE); + return UID2File[FE.getUniqueID()].db.get(); + } + + bool UseMultiVersion(const FileEntry &FE) { + auto it = UID2multi.try_emplace(FE.getUniqueID()); + if (it.second) + it.first->second = multiVersionMatcher->IsMatch(PathFromFileEntry(FE)); + return it.first->second; } }; @@ -281,39 +296,33 @@ try_again: return D; } -const Decl *GetSpecialized(const Decl *D) { - if (!D) - return D; - Decl *Template = nullptr; - if (const CXXRecordDecl *CXXRecord = dyn_cast(D)) { - if (const ClassTemplatePartialSpecializationDecl *PartialSpec = - dyn_cast(CXXRecord)) - Template = PartialSpec->getSpecializedTemplate(); - else if (const ClassTemplateSpecializationDecl *ClassSpec = - dyn_cast(CXXRecord)) { - llvm::PointerUnion - Result = ClassSpec->getSpecializedTemplateOrPartial(); - if (Result.is()) - Template = Result.get(); - else - Template = Result.get(); - - } else - Template = CXXRecord->getInstantiatedFromMemberClass(); - } else if (const FunctionDecl *Function = dyn_cast(D)) { - Template = Function->getPrimaryTemplate(); - if (!Template) - Template = Function->getInstantiatedFromMemberFunction(); - } else if (const VarDecl *Var = dyn_cast(D)) { - if (Var->isStaticDataMember()) - Template = Var->getInstantiatedFromStaticDataMember(); - } else if (const RedeclarableTemplateDecl *Tmpl = - dyn_cast(D)) - Template = Tmpl->getInstantiatedFromMemberTemplate(); - else - return nullptr; - return Template; +const Decl *GetAdjustedDecl(const Decl *D) { + while (D) { + if (auto *R = dyn_cast(D)) { + if (auto *S = dyn_cast(R)) { + if (!S->getTypeAsWritten()) { + llvm::PointerUnion + Result = S->getSpecializedTemplateOrPartial(); + if (Result.is()) + D = Result.get(); + else + D = Result.get(); + continue; + } + } else if (auto *D1 = R->getInstantiatedFromMemberClass()) { + D = D1; + continue; + } + } else if (auto *ED = dyn_cast(D)) { + if (auto *D1 = ED->getInstantiatedFromMemberEnum()) { + D = D1; + continue; + } + } + break; + } + return D; } bool ValidateRecord(const RecordDecl *RD) { @@ -412,20 +421,20 @@ public: return it->second.usr; } - Use GetUse(IndexFile *db, Range range, const DeclContext *DC, + Use GetUse(IndexFile *db, int lid, Range range, const DeclContext *DC, Role role) const { if (!DC) - return Use{{range, 0, SymbolKind::File, role}}; + return {{range, 0, SymbolKind::File, role}, lid}; const Decl *D = cast(DC); switch (GetSymbolKind(D)) { case SymbolKind::Func: - return Use{{range, db->ToFunc(GetUsr(D)).usr, SymbolKind::Func, role}}; + return {{range, db->ToFunc(GetUsr(D)).usr, SymbolKind::Func, role}, lid}; case SymbolKind::Type: - return Use{{range, db->ToType(GetUsr(D)).usr, SymbolKind::Type, role}}; + return {{range, db->ToType(GetUsr(D)).usr, SymbolKind::Type, role}, lid}; case SymbolKind::Var: - return Use{{range, db->ToVar(GetUsr(D)).usr, SymbolKind::Var, role}}; + return {{range, db->ToVar(GetUsr(D)).usr, SymbolKind::Var, role}, lid}; default: - return Use{{range, 0, SymbolKind::File, role}}; + return {{range, 0, SymbolKind::File, role}, lid}; } } @@ -462,6 +471,12 @@ public: std::string name = OS.str(); SimplifyAnonymous(name); + // Remove \n in DeclPrinter.cpp "{\n" + if(!TerseOutput)something + "}" + for (std::string::size_type i = 0;;) { + if ((i = name.find("{\n}", i)) == std::string::npos) + break; + name.replace(i, 3, "{}"); + } auto i = name.find(short_name); if (short_name.size()) while (i != std::string::npos && ((i && isalnum(name[i - 1])) || @@ -509,7 +524,8 @@ public: binding = true; } auto BT = GetBaseType(T, false); - if (!BT.isNull() && (binding || BT->getAs())) { + if (!BT.isNull() && + (binding || BT.getUnqualifiedType()->getAs())) { SmallString<256> Str; llvm::raw_svector_ostream OS(Str); PrintingPolicy PP = GetDefaultPolicy(); @@ -521,7 +537,7 @@ public: def.short_name_offset = Str.size() + qualified.size() - short_name.size(); def.short_name_size = short_name.size(); Str += StringRef(qualified.data(), qualified.size()); - def.detailed_name = Intern(Str.str()); + def.detailed_name = Intern(Str); } else { SetName(D, short_name, qualified, def); } @@ -549,26 +565,32 @@ public: } } + static int GetFileLID(IndexFile *db, SourceManager &SM, const FileEntry &FE) { + auto [it, inserted] = db->uid2lid_and_path.try_emplace(FE.getUniqueID()); + if (inserted) { + it->second.first = db->uid2lid_and_path.size() - 1; + SmallString<256> Path = FE.tryGetRealPathName(); + if (Path.empty()) + Path = FE.getName(); + if (!llvm::sys::path::is_absolute(Path) && + !SM.getFileManager().makeAbsolutePath(Path)) + return -1; + it->second.second = llvm::sys::path::convert_to_slash(Path.str()); + } + return it->second.first; + } + void AddMacroUse(IndexFile *db, SourceManager &SM, Usr usr, SymbolKind kind, SourceLocation Spell) const { const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Spell)); if (!FE) return; - auto UID = FE->getUniqueID(); - auto [it, inserted] = db->uid2lid_and_path.try_emplace(UID); - if (inserted) { - it->second.first = db->uid2lid_and_path.size() - 1; - SmallString<256> Path = FE->tryGetRealPathName(); - if (Path.empty()) - Path = FE->getName(); - if (!llvm::sys::path::is_absolute(Path) && - !SM.getFileManager().makeAbsolutePath(Path)) - return; - it->second.second = Path.str(); - } + int lid = GetFileLID(db, SM, *FE); + if (lid < 0) + return; Range spell = FromTokenRange(SM, Ctx->getLangOpts(), SourceRange(Spell, Spell)); - Use use{{spell, 0, SymbolKind::File, Role::Dynamic}, it->second.first}; + Use use{{spell, 0, SymbolKind::File, Role::Dynamic}, lid}; switch (kind) { case SymbolKind::Func: db->ToFunc(usr).uses.push_back(use); @@ -629,15 +651,27 @@ public: FE = SM.getFileEntryForID(LocFID); if (!FE) return true; - IndexFile *db = param.ConsumeFile(*FE); - if (!db) - return true; + int lid = -1; + IndexFile *db; + if (g_config->index.multiVersion && param.UseMultiVersion(*FE)) { + db = param.ConsumeFile(*SM.getFileEntryForID(SM.getMainFileID())); + if (!db) + return true; + param.SeenFile(*FE); + if (!SM.isInMainFile(R.getBegin())) + lid = GetFileLID(db, SM, *FE); + } else { + db = param.ConsumeFile(*FE); + if (!db) + return true; + } + // spell, extent, comments use OrigD while most others use adjusted |D|. const Decl *OrigD = ASTNode.OrigD; const DeclContext *SemDC = OrigD->getDeclContext(); const DeclContext *LexDC = ASTNode.ContainerDC; Role role = static_cast(Roles); - db->language = std::max(db->language, GetDeclLanguage(OrigD)); + db->language = LanguageId((int)db->language | (int)GetDeclLanguage(D)); bool is_decl = Roles & uint32_t(index::SymbolRole::Declaration); bool is_def = Roles & uint32_t(index::SymbolRole::Definition); @@ -647,23 +681,48 @@ public: IndexType *type = nullptr; IndexVar *var = nullptr; SymbolKind kind = GetSymbolKind(D); + + if (is_def) + switch (D->getKind()) { + case Decl::CXXConversion: // *operator* int => *operator int* + case Decl::CXXDestructor: // *~*A => *~A* + case Decl::CXXMethod: // *operator*= => *operator=* + case Decl::Function: // operator delete + if (Loc.isFileID()) { + SourceRange R = + cast(OrigD)->getNameInfo().getSourceRange(); + if (R.getEnd().isFileID()) + loc = FromTokenRange(SM, Lang, R); + } + break; + default: + break; + } + else { + // e.g. typedef Foo gg; => Foo has an unadjusted `D` + const Decl *D1 = GetAdjustedDecl(D); + if (D1 && D1 != D) + D = D1; + } + IndexParam::DeclInfo *info; Usr usr = GetUsr(D, &info); auto do_def_decl = [&](auto *entity) { if (is_def) { - entity->def.spell = GetUse(db, loc, SemDC, role); + entity->def.spell = GetUse(db, lid, loc, SemDC, role); SourceRange R = OrigD->getSourceRange(); entity->def.extent = - GetUse(db, - R.getBegin().isFileID() - ? FromTokenRange(SM, Lang, OrigD->getSourceRange()) - : loc, + GetUse(db, lid, + R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc, LexDC, Role::None); } else if (is_decl) { - entity->declarations.push_back(GetUse(db, loc, LexDC, role)); + DeclRef &dr = entity->declarations.emplace_back(); + static_cast(dr) = GetUse(db, lid, loc, LexDC, role); + SourceRange R = OrigD->getSourceRange(); + dr.extent = R.getBegin().isFileID() ? FromTokenRange(SM, Lang, R) : loc; } else { - entity->uses.push_back(GetUse(db, loc, LexDC, role)); + entity->uses.push_back(GetUse(db, lid, loc, LexDC, role)); return; } if (entity->def.comments[0] == '\0' && g_config->index.comments) @@ -678,14 +737,16 @@ public: return true; case SymbolKind::Func: func = &db->ToFunc(usr); - // Span one more column to the left/right if D is CXXConstructor. - if (!is_def && !is_decl && D->getKind() == Decl::CXXConstructor) + // Mark as Role::Implicit to span one more column to the left/right. + if (!is_def && !is_decl && + (D->getKind() == Decl::CXXConstructor || + D->getKind() == Decl::CXXConversion)) role = Role(role | Role::Implicit); do_def_decl(func); if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Func, Spell); if (func->def.detailed_name[0] == '\0') - SetName(OrigD, info->short_name, info->qualified, func->def); + SetName(D, info->short_name, info->qualified, func->def); if (is_def || is_decl) { const Decl *DC = cast(SemDC); if (GetSymbolKind(DC) == SymbolKind::Type) @@ -702,8 +763,8 @@ public: do_def_decl(type); if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Type, Spell); - if (type->def.detailed_name[0] == '\0') - SetName(OrigD, info->short_name, info->qualified, type->def); + if (type->def.detailed_name[0] == '\0' && info->short_name.size()) + SetName(D, info->short_name, info->qualified, type->def); if (is_def || is_decl) { const Decl *DC = cast(SemDC); if (GetSymbolKind(DC) == SymbolKind::Type) @@ -716,7 +777,7 @@ public: if (Spell != Loc) AddMacroUse(db, SM, usr, SymbolKind::Var, Spell); if (var->def.detailed_name[0] == '\0') - SetVarName(OrigD, info->short_name, info->qualified, var->def); + SetVarName(D, info->short_name, info->qualified, var->def); QualType T; if (auto *VD = dyn_cast(D)) T = VD->getType(); @@ -733,26 +794,21 @@ public: Usr usr1 = static_cast(BT->getKind()); var->def.type = usr1; db->ToType(usr1).instances.push_back(usr); - } else { - for (const Decl *D1 = GetTypeDecl(T); D1; D1 = GetSpecialized(D1)) { - IndexParam::DeclInfo *info1; - Usr usr1 = GetUsr(D1, &info1); - auto it = db->usr2type.find(usr1); - if (it != db->usr2type.end()) { - var->def.type = usr1; - it->second.instances.push_back(usr); - break; - } + } else if (const Decl *D1 = GetAdjustedDecl(GetTypeDecl(T))) { + if (isa(D1)) { // e.g. TemplateTypeParmDecl is not handled by // handleDeclOccurence. SourceRange R1 = D1->getSourceRange(); if (SM.getFileID(R1.getBegin()) == LocFID) { + IndexParam::DeclInfo *info1; + Usr usr1 = GetUsr(D1, &info1); IndexType &type1 = db->ToType(usr1); SourceLocation L1 = D1->getLocation(); - type1.def.spell = GetUse(db, FromTokenRange(SM, Lang, {L1, L1}), - SemDC, Role::Definition); - type1.def.extent = - GetUse(db, FromTokenRange(SM, Lang, R1), LexDC, Role::None); + type1.def.spell = + GetUse(db, lid, FromTokenRange(SM, Lang, {L1, L1}), SemDC, + Role::Definition); + type1.def.extent = GetUse(db, lid, FromTokenRange(SM, Lang, R1), + LexDC, Role::None); type1.def.detailed_name = Intern(info1->short_name); type1.def.short_name_size = int16_t(info1->short_name.size()); type1.def.kind = lsSymbolKind::TypeParameter; @@ -761,16 +817,21 @@ public: break; } } + + IndexParam::DeclInfo *info1; + Usr usr1 = GetUsr(D1, &info1); + var->def.type = usr1; + db->ToType(usr1).instances.push_back(usr); } } } else if (!var->def.spell && var->declarations.empty()) { // e.g. lambda parameter - SourceLocation L = OrigD->getLocation(); + SourceLocation L = D->getLocation(); if (SM.getFileID(L) == LocFID) { - var->def.spell = GetUse(db, FromTokenRange(SM, Lang, {L, L}), SemDC, - Role::Definition); + var->def.spell = GetUse(db, lid, FromTokenRange(SM, Lang, {L, L}), + SemDC, Role::Definition); var->def.extent = - GetUse(db, FromTokenRange(SM, Lang, OrigD->getSourceRange()), + GetUse(db, lid, FromTokenRange(SM, Lang, D->getSourceRange()), LexDC, Role::None); } } @@ -780,8 +841,8 @@ public: switch (D->getKind()) { case Decl::Namespace: type->def.kind = lsSymbolKind::Namespace; - if (OrigD->isFirstDecl()) { - auto *ND = cast(OrigD); + if (D->isFirstDecl()) { + auto *ND = cast(D); auto *ND1 = cast(ND->getParent()); if (isa(ND1)) { Usr usr1 = GetUsr(ND1); @@ -832,32 +893,42 @@ public: break; case Decl::CXXRecord: if (is_def) { - auto *RD = dyn_cast(OrigD); - if (RD && RD->hasDefinition()) { - for (const CXXBaseSpecifier &Base : RD->bases()) { - QualType T = Base.getType(); - const NamedDecl *BaseD = nullptr; - if (auto *TDT = T->getAs()) { - BaseD = TDT->getDecl(); - } else if (auto *TST = T->getAs()) { - BaseD = TST->getTemplateName().getAsTemplateDecl(); - } else if (auto *RT = T->getAs()) { - BaseD = RT->getDecl(); - } - if (BaseD) { + auto *RD = dyn_cast(D); + if (RD && RD->hasDefinition()) + for (const CXXBaseSpecifier &Base : RD->bases()) + if (const Decl *BaseD = + GetAdjustedDecl(GetTypeDecl(Base.getType()))) { Usr usr1 = GetUsr(BaseD); type->def.bases.push_back(usr1); db->ToType(usr1).derived.push_back(usr); } - } - } } [[fallthrough]]; case Decl::Record: - if (auto *RD = dyn_cast(OrigD)) { + if (auto *RD = dyn_cast(D)) { // spec has no Union, use Class type->def.kind = RD->getTagKind() == TTK_Struct ? lsSymbolKind::Struct : lsSymbolKind::Class; + if (type->def.detailed_name[0] == '\0' && info->short_name.empty()) { + StringRef Tag; + switch (RD->getTagKind()) { + case TTK_Struct: Tag = "struct"; break; + case TTK_Interface: Tag = "__interface"; break; + case TTK_Union: Tag = "union"; break; + case TTK_Class: Tag = "class"; break; + case TTK_Enum: Tag = "enum"; break; + } + if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl()) { + StringRef Name = TD->getName(); + std::string name = ("anon " + Tag + " " + Name).str(); + type->def.detailed_name = Intern(name); + type->def.short_name_size = name.size(); + } else { + std::string name = ("anon " + Tag).str(); + type->def.detailed_name = Intern(name); + type->def.short_name_size = name.size(); + } + } if (is_def) { SmallVector, 2> Stack{{RD, 0}}; llvm::DenseSet Seen; @@ -867,10 +938,10 @@ public: std::tie(RD, offset) = Stack.back(); Stack.pop_back(); if (!RD->isCompleteDefinition() || RD->isDependentType() || - !ValidateRecord(RD)) + RD->isInvalidDecl() || !ValidateRecord(RD)) offset = -1; for (FieldDecl *FD : RD->fields()) { - int offset1 = offset >= 0 ? offset + Ctx->getFieldOffset(FD) : -1; + int offset1 = offset < 0 ? -1 : offset + Ctx->getFieldOffset(FD); if (FD->getIdentifier()) type->def.vars.emplace_back(GetUsr(FD), offset1); else if (const auto *RT1 = FD->getType()->getAs()) { @@ -917,7 +988,7 @@ public: if (auto *TD = dyn_cast(D)) { bool specialization = false; QualType T = TD->getUnderlyingType(); - if (const Decl *D1 = GetTypeDecl(T, &specialization)) { + if (const Decl *D1 = GetAdjustedDecl(GetTypeDecl(T, &specialization))) { Usr usr1 = GetUsr(D1); IndexType &type1 = db->ToType(usr1); type->def.alias_of = usr1; @@ -927,7 +998,8 @@ public: SourceLocation L1 = TSI->getTypeLoc().getBeginLoc(); if (SM.getFileID(L1) == LocFID) { Range loc1 = FromTokenRange(SM, Lang, {L1, L1}); - type1.uses.push_back(GetUse(db, loc1, LexDC, Role::Reference)); + type1.uses.push_back( + GetUse(db, lid, loc1, LexDC, Role::Reference)); } } } @@ -982,7 +1054,6 @@ public: break; case Decl::EnumConstant: var->def.kind = lsSymbolKind::EnumMember; - // TODO Pretty printer may print = if (is_def && strchr(var->def.detailed_name, '=') == nullptr) { auto *ECD = cast(D); const auto &Val = ECD->getInitVal(); @@ -1037,9 +1108,9 @@ public: if (!FE) return; if (IndexFile *db = param.ConsumeFile(*FE)) { - std::string file_name = FileName(*File); - if (file_name.size()) - db->includes.push_back({spell.start.line, std::move(file_name)}); + std::string path = PathFromFileEntry(*File); + if (path.size()) + db->includes.push_back({spell.start.line, Intern(path)}); } } void MacroDefined(const Token &Tok, const MacroDirective *MD) override { @@ -1054,8 +1125,11 @@ public: IndexVar &var = db->ToVar(usr); auto range = FromTokenRange(SM, Lang, {L, L}, &UniqueID); var.def.kind = lsSymbolKind::Macro; - if (var.def.spell) - var.declarations.push_back(*var.def.spell); + if (var.def.spell) { + DeclRef &d = var.declarations.emplace_back(); + static_cast(d) = *var.def.spell; + d.extent = var.def.spell->range; + } var.def.spell = Use{{range, 0, SymbolKind::File, Role::Definition}}; const MacroInfo *MI = MD->getMacroInfo(); SourceRange R(MI->getDefinitionLoc(), MI->getDefinitionEndLoc()); @@ -1080,8 +1154,7 @@ public: if (!FE) return; if (IndexFile *db = param.ConsumeFile(*FE)) { - auto [Name, usr] = GetMacro(Tok); - IndexVar &var = db->ToVar(usr); + IndexVar &var = db->ToVar(GetMacro(Tok).second); var.uses.push_back( {{FromTokenRange(SM, param.Ctx->getLangOpts(), {L, L}, &UniqueID), 0, SymbolKind::File, Role::Dynamic}}); @@ -1097,9 +1170,10 @@ public: void SourceRangeSkipped(SourceRange Range, SourceLocation EndifLoc) override { llvm::sys::fs::UniqueID UniqueID; auto range = FromCharRange(SM, param.Ctx->getLangOpts(), Range, &UniqueID); - const FileEntry *FE = SM.getFileEntryForID(SM.getFileID(Range.getBegin())); - if (IndexFile *db = param.ConsumeFile(*FE)) - db->skipped_ranges.push_back(range); + if (const FileEntry *FE = + SM.getFileEntryForID(SM.getFileID(Range.getBegin()))) + if (IndexFile *db = param.ConsumeFile(*FE)) + db->skipped_ranges.push_back(range); } }; @@ -1118,8 +1192,8 @@ public: }; } // namespace -const int IndexFile::kMajorVersion = 17; -const int IndexFile::kMinorVersion = 1; +const int IndexFile::kMajorVersion = 18; +const int IndexFile::kMinorVersion = 0; IndexFile::IndexFile(llvm::sys::fs::UniqueID UniqueID, const std::string &path, const std::string &contents) @@ -1160,28 +1234,28 @@ template void Uniquify(std::vector &a) { } namespace ccls::idx { -std::vector> -Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, - const std::vector &args, - const std::vector &file_contents) { - if (!g_config->index.enabled) - return {}; +void Init() { + multiVersionMatcher = new GroupMatch(g_config->index.multiVersionWhitelist, + g_config->index.multiVersionBlacklist); +} - std::vector Args; - for (auto &arg : args) - Args.push_back(arg.c_str()); - auto PCHCO = std::make_shared(); - IntrusiveRefCntPtr Diags( - CompilerInstance::createDiagnostics(new DiagnosticOptions)); - std::shared_ptr CI = - createInvocationFromCommandLine(Args, Diags); +std::vector> +Index(CompletionManager *completion, WorkingFiles *wfiles, VFS *vfs, + const std::string &opt_wdir, const std::string &file, + const std::vector &args, + const std::vector> &remapped, bool &ok) { + ok = true; + auto PCH = std::make_shared(); + llvm::IntrusiveRefCntPtr FS = vfs::getRealFileSystem(); + std::shared_ptr CI = BuildCompilerInvocation(args, FS); + // e.g. .s if (!CI) return {}; + ok = false; // -fparse-all-comments enables documentation in the indexer and in // code completion. if (g_config->index.comments > 1) CI->getLangOpts()->CommentOpts.ParseAllComments = true; - CI->getLangOpts()->SpellChecking = false; { // FileSystemOptions& FSOpts = CI->getFileSystemOpts(); // if (FSOpts.WorkingDir.empty()) @@ -1193,21 +1267,47 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, // HSOpts.UseBuiltinIncludes) // HSOpts.ResourceDir = g_config->clang.resourceDir; } - - std::vector> BufOwner; - for (auto &c : file_contents) { - std::unique_ptr MB = - llvm::MemoryBuffer::getMemBufferCopy(c.content, c.path); - CI->getPreprocessorOpts().addRemappedFile(c.path, MB.get()); - BufOwner.push_back(std::move(MB)); + std::string buf = wfiles->GetContent(file); + std::vector> Bufs; + if (buf.size()) { + // If there is a completion session, reuse its preamble if exists. + bool done_remap = false; +#if 0 + std::shared_ptr session = + completion->TryGetSession(file, false, false); + if (session) + if (auto preamble = session->GetPreamble()) { + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(buf)); + auto Bounds = ComputePreambleBounds(*CI->getLangOpts(), Bufs.back().get(), 0); + if (preamble->Preamble.CanReuse(*CI, Bufs.back().get(), Bounds, + FS.get())) { + preamble->Preamble.AddImplicitPreamble(*CI, FS, Bufs.back().get()); + done_remap = true; + } + } +#endif + for (auto &[filename, content] : remapped) { + if (filename == file && done_remap) + continue; + Bufs.push_back(llvm::MemoryBuffer::getMemBuffer(content)); + CI->getPreprocessorOpts().addRemappedFile( + filename == file ? CI->getFrontendOpts().Inputs[0].getFile() + : StringRef(filename), + Bufs.back().get()); + } } - auto Unit = ASTUnit::create(CI, Diags, true, true); - if (!Unit) + DiagnosticConsumer DC; + auto Clang = std::make_unique(PCH); + Clang->setInvocation(std::move(CI)); + Clang->setVirtualFileSystem(FS); + Clang->createDiagnostics(&DC, false); + Clang->setTarget(TargetInfo::CreateTargetInfo( + Clang->getDiagnostics(), Clang->getInvocation().TargetOpts)); + if (!Clang->hasTarget()) return {}; - FileConsumer file_consumer(vfs, file); - IndexParam param(*Unit, &file_consumer); + IndexParam param(*vfs); auto DataConsumer = std::make_shared(param); index::IndexingOptions IndexOpts; @@ -1218,38 +1318,36 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, IndexOpts.IndexImplicitInstantiation = true; #endif - std::unique_ptr IndexAction = createIndexingAction( + std::unique_ptr Action = createIndexingAction( DataConsumer, IndexOpts, std::make_unique(param)); - DiagnosticErrorTrap DiagTrap(*Diags); - llvm::CrashRecoveryContext CRC; - auto compile = [&]() { - ASTUnit::LoadFromCompilerInvocationAction( - std::move(CI), PCHCO, Diags, IndexAction.get(), Unit.get(), - /*Persistent=*/true, /*ResourceDir=*/"", - /*OnlyLocalDecls=*/true, - /*CaptureDiagnostics=*/true, 0, false, false, - /*UserFilesAreVolatile=*/true); - }; - if (!CRC.RunSafely(compile)) { - LOG_S(ERROR) << "clang crashed for " << file; - return {}; + { + llvm::CrashRecoveryContext CRC; + auto parse = [&]() { + if (!Action->BeginSourceFile(*Clang, Clang->getFrontendOpts().Inputs[0])) + return; + if (!Action->Execute()) + return; + Action->EndSourceFile(); + ok = true; + }; + if (!CRC.RunSafely(parse)) { + LOG_S(ERROR) << "clang crashed for " << file; + return {}; + } } - if (!Unit) { + if (!ok) { LOG_S(ERROR) << "failed to index " << file; return {}; } + for (auto &Buf : Bufs) + Buf.release(); - const SourceManager &SM = Unit->getSourceManager(); - const FileEntry *FE = SM.getFileEntryForID(SM.getMainFileID()); - IndexFile *main_file = param.ConsumeFile(*FE); - std::unordered_map inc_to_line; - if (main_file) - for (auto &inc : main_file->includes) - inc_to_line[inc.resolved_path] = inc.line; - - auto result = param.file_consumer->TakeLocalState(); - for (std::unique_ptr &entry : result) { + std::vector> result; + for (auto &it : param.UID2File) { + if (!it.second.db) + continue; + std::unique_ptr &entry = it.second.db; entry->import_file = file; entry->args = args; for (auto &[_, it] : entry->uid2lid_and_path) @@ -1270,30 +1368,16 @@ Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, for (auto &it : entry->usr2var) Uniquify(it.second.uses); - if (main_file) { - // If there are errors, show at least one at the include position. - auto it = inc_to_line.find(entry->path); - if (it != inc_to_line.end()) { - int line = it->second; - for (auto ls_diagnostic : entry->diagnostics_) { - if (ls_diagnostic.severity != lsDiagnosticSeverity::Error) - continue; - ls_diagnostic.range = - lsRange{lsPosition{line, 10}, lsPosition{line, 10}}; - main_file->diagnostics_.push_back(ls_diagnostic); - break; - } - } + // Update dependencies for the file. + for (auto &[_, file] : param.UID2File) { + const std::string &path = file.path; + if (path == entry->path) + entry->mtime = file.mtime; + else if (path != entry->import_file) + entry->dependencies[llvm::CachedHashStringRef(Intern(path))] = + file.mtime; } - - // Update file contents and modification time. - entry->last_write_time = param.file2write_time[entry->path]; - - // Update dependencies for the file. Do not include the file in its own - // dependency set. - for (auto &[_, path] : param.SeenUniqueID) - if (path != entry->path && path != entry->import_file) - entry->dependencies[path] = param.file2write_time[path]; + result.push_back(std::move(entry)); } return result; @@ -1343,8 +1427,7 @@ void Reflect(Reader &vis, Use &v) { v.usr = strtoull(s + 1, &s, 10); v.kind = static_cast(strtol(s + 1, &s, 10)); v.role = static_cast(strtol(s + 1, &s, 10)); - if (*s == '|') - v.file_id = static_cast(strtol(s + 1, &s, 10)); + v.file_id = static_cast(strtol(s + 1, &s, 10)); } else { Reflect(vis, static_cast(v)); Reflect(vis, v.file_id); @@ -1353,13 +1436,9 @@ void Reflect(Reader &vis, Use &v) { void Reflect(Writer &vis, Use &v) { if (vis.Format() == SerializeFormat::Json) { char buf[99]; - if (v.file_id == -1) - snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d", - v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role)); - else - snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d|%d", - v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role), - v.file_id); + snprintf(buf, sizeof buf, "%s|%" PRIu64 "|%d|%d|%d", + v.range.ToString().c_str(), v.usr, int(v.kind), int(v.role), + v.file_id); std::string s(buf); Reflect(vis, s); } else { @@ -1367,3 +1446,34 @@ void Reflect(Writer &vis, Use &v) { Reflect(vis, v.file_id); } } + +void Reflect(Reader &vis, DeclRef &v) { + if (vis.Format() == SerializeFormat::Json) { + std::string t = vis.GetString(); + char *s = const_cast(t.c_str()); + v.range = Range::FromString(s); + s = strchr(s, '|') + 1; + v.extent = Range::FromString(s); + s = strchr(s, '|') + 1; + v.usr = strtoull(s, &s, 10); + v.kind = static_cast(strtol(s + 1, &s, 10)); + v.role = static_cast(strtol(s + 1, &s, 10)); + v.file_id = static_cast(strtol(s + 1, &s, 10)); + } else { + Reflect(vis, static_cast(v)); + Reflect(vis, v.extent); + } +} +void Reflect(Writer &vis, DeclRef &v) { + if (vis.Format() == SerializeFormat::Json) { + char buf[99]; + snprintf(buf, sizeof buf, "%s|%s|%" PRIu64 "|%d|%d|%d", + v.range.ToString().c_str(), v.extent.ToString().c_str(), v.usr, + int(v.kind), int(v.role), v.file_id); + std::string s(buf); + Reflect(vis, s); + } else { + Reflect(vis, static_cast(v)); + Reflect(vis, v.extent); + } +} diff --git a/src/indexer.h b/src/indexer.h index 151bb0b0..2a911067 100644 --- a/src/indexer.h +++ b/src/indexer.h @@ -15,8 +15,6 @@ limitations under the License. #pragma once -#include "clang_utils.h" -#include "file_consumer.h" #include "language.h" #include "lsp.h" #include "lsp_diagnostic.h" @@ -26,11 +24,11 @@ limitations under the License. #include "symbol.h" #include "utils.h" +#include #include -#include +#include +#include -#include -#include #include #include #include @@ -82,10 +80,17 @@ struct Use : Reference { }; MAKE_HASHABLE(Use, t.range, t.file_id) +struct DeclRef : Use { + Range extent; +}; +MAKE_HASHABLE(DeclRef, t.range, t.file_id) + void Reflect(Reader &visitor, Reference &value); void Reflect(Writer &visitor, Reference &value); void Reflect(Reader &visitor, Use &value); void Reflect(Writer &visitor, Use &value); +void Reflect(Reader &visitor, DeclRef &value); +void Reflect(Writer &visitor, DeclRef &value); template struct NameMixin { std::string_view Name(bool qualified) const { @@ -134,7 +139,7 @@ struct IndexFunc : NameMixin { using Def = FuncDef; Usr usr; Def def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; }; @@ -174,7 +179,7 @@ struct IndexType { using Def = TypeDef; Usr usr; Def def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; std::vector instances; @@ -216,7 +221,7 @@ struct IndexVar { using Def = VarDef; Usr usr; Def def; - std::vector declarations; + std::vector declarations; std::vector uses; }; @@ -225,9 +230,19 @@ struct IndexInclude { // information - a line is good enough for clicking. int line = 0; // Absolute path to the index. - std::string resolved_path; + const char *resolved_path; }; +namespace std { +template <> struct hash { + std::size_t operator()(llvm::sys::fs::UniqueID ID) const { + size_t ret = ID.getDevice(); + hash_combine(ret, ID.getFile()); + return ret; + } +}; +} // namespace std + struct IndexFile { // For both JSON and MessagePack cache files. static const int kMajorVersion; @@ -239,9 +254,10 @@ struct IndexFile { llvm::sys::fs::UniqueID UniqueID; std::string path; - std::vector args; - int64_t last_write_time = 0; - LanguageId language = LanguageId::Unknown; + std::vector args; + // This is unfortunately time_t as used by clang::FileEntry + int64_t mtime = 0; + LanguageId language = LanguageId::C; // uid2lid_and_path is used to generate lid2path, but not serialized. std::unordered_map> @@ -258,13 +274,11 @@ struct IndexFile { std::vector skipped_ranges; std::vector includes; - llvm::StringMap dependencies; + llvm::DenseMap dependencies; std::unordered_map usr2func; std::unordered_map usr2type; std::unordered_map usr2var; - // Diagnostics found when indexing this file. Not serialized. - std::vector diagnostics_; // File contents at the time of index. Not serialized. std::string file_contents; @@ -278,9 +292,16 @@ struct IndexFile { std::string ToString(); }; +struct CompletionManager; +struct WorkingFiles; +struct VFS; + namespace ccls::idx { +void Init(); std::vector> -Index(VFS *vfs, const std::string &opt_wdir, const std::string &file, - const std::vector &args, - const std::vector &file_contents); -} +Index(CompletionManager *complete, WorkingFiles *wfiles, VFS *vfs, + const std::string &opt_wdir, const std::string &file, + const std::vector &args, + const std::vector> &remapped, + bool &ok); +} // namespace ccls::idx diff --git a/src/language.h b/src/language.h index 846185b5..d53b7920 100644 --- a/src/language.h +++ b/src/language.h @@ -22,7 +22,7 @@ limitations under the License. // Used to identify the language at a file level. The ordering is important, as // a file previously identified as `C`, will be changed to `Cpp` if it // encounters a c++ declaration. -enum class LanguageId { Unknown = 0, C = 1, Cpp = 2, ObjC = 3, ObjCpp = 4 }; +enum class LanguageId { Unknown = -1, C = 0, Cpp = 1, ObjC = 2, ObjCpp = 3 }; MAKE_REFLECT_TYPE_PROXY(LanguageId); LanguageId SourceFileLanguage(std::string_view path); diff --git a/src/lsp.cc b/src/lsp.cc index afb0b76c..6fac3d6c 100644 --- a/src/lsp.cc +++ b/src/lsp.cc @@ -220,10 +220,15 @@ void lsDocumentUri::SetPath(const std::string &path) { } std::string lsDocumentUri::GetPath() const { - if (raw_uri.compare(0, 8, "file:///")) + if (raw_uri.compare(0, 7, "file://")) { + LOG_S(WARNING) + << "Received potentially bad URI (not starting with file://): " + << raw_uri; return raw_uri; + } std::string ret; #ifdef _WIN32 + // Skipping the initial "/" on Windows size_t i = 8; #else size_t i = 7; @@ -236,8 +241,14 @@ std::string lsDocumentUri::GetPath() const { ret.push_back(from_hex(raw_uri[i + 1]) * 16 + from_hex(raw_uri[i + 2])); i += 2; } else - ret.push_back(raw_uri[i] == '\\' ? '/' : raw_uri[i]); + ret.push_back(raw_uri[i]); } +#ifdef _WIN32 + std::replace(ret.begin(), ret.end(), '\\', '/'); + if (ret.size() > 1 && ret[0] >= 'a' && ret[0] <= 'z' && ret[1] == ':') { + ret[0] = toupper(ret[0]); + } +#endif return ret; } diff --git a/src/lsp.h b/src/lsp.h index ef4ada8c..6e4c5d22 100644 --- a/src/lsp.h +++ b/src/lsp.h @@ -91,6 +91,8 @@ struct lsResponseError { void Write(Writer &visitor); }; +constexpr std::string_view ccls_xref("ccls.xref"); + ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// @@ -205,43 +207,6 @@ struct lsLocationEx : lsLocation { }; MAKE_REFLECT_STRUCT(lsLocationEx, uri, range, containerName, parentKind, role); -template struct lsCommand { - // Title of the command (ie, 'save') - std::string title; - // Actual command identifier. - std::string command; - // Arguments to run the command with. - // **NOTE** This must be serialized as an array. Use - // MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY. - T arguments; -}; -template -void Reflect(TVisitor &visitor, lsCommand &value) { - REFLECT_MEMBER_START(); - REFLECT_MEMBER(title); - REFLECT_MEMBER(command); - REFLECT_MEMBER(arguments); - REFLECT_MEMBER_END(); -} - -template struct lsCodeLens { - // The range in which this code lens is valid. Should only span a single line. - lsRange range; - // The command this code lens represents. - std::optional> command; - // A data entry field that is preserved on a code lens item between - // a code lens and a code lens resolve request. - TData data; -}; -template -void Reflect(TVisitor &visitor, lsCodeLens &value) { - REFLECT_MEMBER_START(); - REFLECT_MEMBER(range); - REFLECT_MEMBER(command); - REFLECT_MEMBER(data); - REFLECT_MEMBER_END(); -} - struct lsTextDocumentIdentifier { lsDocumentUri uri; }; diff --git a/src/main.cc b/src/main.cc index 55880343..66e76f86 100644 --- a/src/main.cc +++ b/src/main.cc @@ -20,15 +20,12 @@ limitations under the License. #include "serializers/json.h" #include "test.h" #include "working_files.h" -using namespace ccls; #include #include #include #include #include -using namespace llvm; -using namespace llvm::cl; #include @@ -38,6 +35,10 @@ using namespace llvm::cl; #include #include +using namespace ccls; +using namespace llvm; +using namespace llvm::cl; + std::string g_init_options; namespace { @@ -101,7 +102,7 @@ int main(int argc, char **argv) { if (!opt_init.empty()) { // We check syntax error here but override client-side // initializationOptions in messages/initialize.cc - g_init_options = opt_init; + g_init_options = opt_init.getValue(); rapidjson::Document reader; rapidjson::ParseResult ok = reader.Parse(g_init_options.c_str()); if (!ok) { diff --git a/src/match.cc b/src/match.cc index 3ddb0c37..b86dfd90 100644 --- a/src/match.cc +++ b/src/match.cc @@ -19,18 +19,7 @@ limitations under the License. #include "pipeline.hh" using namespace ccls; -// static std::optional Matcher::Create(const std::string &search) { - /* - std::string real_search; - real_search.reserve(search.size() * 3 + 2); - for (auto c : search) { - real_search += ".*"; - real_search += c; - } - real_search += ".*"; - */ - try { Matcher m; m.regex_string = search; @@ -73,18 +62,16 @@ GroupMatch::GroupMatch(const std::vector &whitelist, bool GroupMatch::IsMatch(const std::string &value, std::string *match_failure_reason) const { - for (const Matcher &m : whitelist) { + for (const Matcher &m : whitelist) if (m.IsMatch(value)) return true; - } - for (const Matcher &m : blacklist) { + for (const Matcher &m : blacklist) if (m.IsMatch(value)) { if (match_failure_reason) *match_failure_reason = "blacklist \"" + m.regex_string + "\""; return false; } - } return true; } diff --git a/src/message_handler.cc b/src/message_handler.cc index 706bfe91..98ef5dde 100644 --- a/src/message_handler.cc +++ b/src/message_handler.cc @@ -16,6 +16,7 @@ limitations under the License. #include "message_handler.h" #include "log.hh" +#include "match.h" #include "pipeline.hh" #include "project.h" #include "query_utils.h" @@ -59,74 +60,6 @@ struct ScanLineEvent { }; } // namespace -SemanticHighlightSymbolCache::Entry::Entry( - SemanticHighlightSymbolCache *all_caches, const std::string &path) - : all_caches_(all_caches), path(path) {} - -std::optional SemanticHighlightSymbolCache::Entry::TryGetStableId( - SymbolKind kind, const std::string &detailed_name) { - TNameToId *map = GetMapForSymbol_(kind); - auto it = map->find(detailed_name); - if (it != map->end()) - return it->second; - - return std::nullopt; -} - -int SemanticHighlightSymbolCache::Entry::GetStableId( - SymbolKind kind, const std::string &detailed_name) { - std::optional id = TryGetStableId(kind, detailed_name); - if (id) - return *id; - - // Create a new id. First try to find a key in another map. - all_caches_->cache_.IterateValues([&](const std::shared_ptr &entry) { - std::optional other_id = entry->TryGetStableId(kind, detailed_name); - if (other_id) { - id = other_id; - return false; - } - return true; - }); - - // Create a new id. - TNameToId *map = GetMapForSymbol_(kind); - if (!id) - id = all_caches_->next_stable_id_++; - return (*map)[detailed_name] = *id; -} - -SemanticHighlightSymbolCache::Entry::TNameToId * -SemanticHighlightSymbolCache::Entry::GetMapForSymbol_(SymbolKind kind) { - switch (kind) { - case SymbolKind::Type: - return &detailed_type_name_to_stable_id; - case SymbolKind::Func: - return &detailed_func_name_to_stable_id; - case SymbolKind::Var: - return &detailed_var_name_to_stable_id; - case SymbolKind::File: - case SymbolKind::Invalid: - break; - } - assert(false); - return nullptr; -} - -SemanticHighlightSymbolCache::SemanticHighlightSymbolCache() - : cache_(kCacheSize) {} - -void SemanticHighlightSymbolCache::Init() { - match_ = std::make_unique(g_config->highlight.whitelist, - g_config->highlight.blacklist); -} - -std::shared_ptr -SemanticHighlightSymbolCache::GetCacheForFile(const std::string &path) { - return cache_.Get( - path, [&, this]() { return std::make_shared(this, path); }); -} - MessageHandler::MessageHandler() { // Dynamically allocate |message_handlers|, otherwise there will be static // initialization order races. @@ -160,8 +93,8 @@ bool FindFileOrFail(DB *db, Project *project, std::optional id, bool indexing; { std::lock_guard lock(project->mutex_); - indexing = project->absolute_path_to_entry_index_.find(absolute_path) != - project->absolute_path_to_entry_index_.end(); + indexing = project->path_to_entry_index.find(absolute_path) != + project->path_to_entry_index.end(); } if (indexing) LOG_S(INFO) << "\"" << absolute_path << "\" is being indexed."; @@ -196,28 +129,30 @@ void EmitSkippedRanges(WorkingFile *working_file, pipeline::WriteStdout(kMethodType_CclsPublishSkippedRanges, out); } -void EmitSemanticHighlighting(DB *db, - SemanticHighlightSymbolCache *semantic_cache, - WorkingFile *wfile, QueryFile *file) { +void EmitSemanticHighlighting(DB *db, WorkingFile *wfile, QueryFile *file) { + static GroupMatch match(g_config->highlight.whitelist, + g_config->highlight.blacklist); assert(file->def); - if (wfile->buffer_content.size() > g_config->largeFileSize || - !semantic_cache->match_->IsMatch(file->def->path)) + if (wfile->buffer_content.size() > g_config->highlight.largeFileSize || + !match.IsMatch(file->def->path)) return; - auto semantic_cache_for_file = - semantic_cache->GetCacheForFile(file->def->path); // Group symbols together. std::unordered_map grouped_symbols; - for (SymbolRef sym : file->def->all_symbols) { + for (auto &sym_refcnt : file->symbol2refcnt) { + if (sym_refcnt.second <= 0) continue; + SymbolRef sym = sym_refcnt.first; std::string_view detailed_name; lsSymbolKind parent_kind = lsSymbolKind::Unknown; lsSymbolKind kind = lsSymbolKind::Unknown; uint8_t storage = SC_None; + int idx; // This switch statement also filters out symbols that are not highlighted. switch (sym.kind) { case SymbolKind::Func: { - const QueryFunc &func = db->GetFunc(sym); + idx = db->func_usr[sym.usr]; + const QueryFunc &func = db->funcs[idx]; const QueryFunc::Def *def = func.AnyDef(); if (!def) continue; // applies to for loop @@ -258,8 +193,10 @@ void EmitSemanticHighlighting(DB *db, sym.range.end.column = start_col + concise_name.size(); break; } - case SymbolKind::Type: - for (auto &def : db->GetType(sym).def) { + case SymbolKind::Type: { + idx = db->type_usr[sym.usr]; + const QueryType &type = db->types[idx]; + for (auto &def : type.def) { kind = def.kind; detailed_name = def.detailed_name; if (def.spell) { @@ -268,8 +205,10 @@ void EmitSemanticHighlighting(DB *db, } } break; + } case SymbolKind::Var: { - const QueryVar &var = db->GetVar(sym); + idx = db->var_usr[sym.usr]; + const QueryVar &var = db->vars[idx]; for (auto &def : var.def) { kind = def.kind; storage = def.storage; @@ -298,8 +237,7 @@ void EmitSemanticHighlighting(DB *db, it->second.lsRanges.push_back(*loc); } else { Out_CclsPublishSemanticHighlighting::Symbol symbol; - symbol.stableId = semantic_cache_for_file->GetStableId( - sym.kind, std::string(detailed_name)); + symbol.stableId = idx; symbol.parentKind = parent_kind; symbol.kind = kind; symbol.storage = storage; diff --git a/src/message_handler.h b/src/message_handler.h index 99da9d30..33bbb6f3 100644 --- a/src/message_handler.h +++ b/src/message_handler.h @@ -15,9 +15,7 @@ limitations under the License. #pragma once -#include "lru_cache.h" #include "lsp.h" -#include "match.h" #include "method.h" #include "query.h" @@ -26,12 +24,10 @@ limitations under the License. #include #include -struct ClangCompleteManager; -struct CodeCompleteCache; +struct CompletionManager; struct Config; -class DiagnosticsPublisher; +struct GroupMatch; struct VFS; -struct ImportManager; struct IncludeComplete; struct MultiQueueWaiter; struct Project; @@ -39,39 +35,6 @@ struct DB; struct WorkingFile; struct WorkingFiles; -// Caches symbols for a single file for semantic highlighting to provide -// relatively stable ids. Only supports xxx files at a time. -struct SemanticHighlightSymbolCache { - struct Entry { - SemanticHighlightSymbolCache *all_caches_ = nullptr; - - // The path this cache belongs to. - std::string path; - // Detailed symbol name to stable id. - using TNameToId = std::unordered_map; - TNameToId detailed_type_name_to_stable_id; - TNameToId detailed_func_name_to_stable_id; - TNameToId detailed_var_name_to_stable_id; - - Entry(SemanticHighlightSymbolCache *all_caches, const std::string &path); - - std::optional TryGetStableId(SymbolKind kind, - const std::string &detailed_name); - int GetStableId(SymbolKind kind, const std::string &detailed_name); - - TNameToId *GetMapForSymbol_(SymbolKind kind); - }; - - constexpr static int kCacheSize = 10; - LruCache cache_; - uint32_t next_stable_id_ = 0; - std::unique_ptr match_; - - SemanticHighlightSymbolCache(); - void Init(); - std::shared_ptr GetCacheForFile(const std::string &path); -}; - struct Out_CclsPublishSemanticHighlighting : public lsOutMessage { struct Symbol { @@ -112,18 +75,11 @@ MAKE_REFLECT_STRUCT(Out_CclsPublishSemanticHighlighting, jsonrpc, method, struct MessageHandler { DB *db = nullptr; - MultiQueueWaiter *waiter = nullptr; Project *project = nullptr; - DiagnosticsPublisher *diag_pub = nullptr; VFS *vfs = nullptr; - ImportManager *import_manager = nullptr; - SemanticHighlightSymbolCache *semantic_cache = nullptr; WorkingFiles *working_files = nullptr; - ClangCompleteManager *clang_complete = nullptr; + CompletionManager *clang_complete = nullptr; IncludeComplete *include_complete = nullptr; - CodeCompleteCache *global_code_complete_cache = nullptr; - CodeCompleteCache *non_global_code_complete_cache = nullptr; - CodeCompleteCache *signature_cache = nullptr; virtual MethodType GetMethodType() const = 0; virtual void Run(std::unique_ptr message) = 0; @@ -150,6 +106,5 @@ bool FindFileOrFail(DB *db, Project *project, std::optional id, void EmitSkippedRanges(WorkingFile *working_file, const std::vector &skipped_ranges); -void EmitSemanticHighlighting(DB *db, - SemanticHighlightSymbolCache *semantic_cache, - WorkingFile *working_file, QueryFile *file); +void EmitSemanticHighlighting(DB *db, WorkingFile *working_file, + QueryFile *file); diff --git a/src/messages/ccls_base.cc b/src/messages/ccls_base.cc deleted file mode 100644 index b5f2b8bb..00000000 --- a/src/messages/ccls_base.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -namespace { - -MethodType kMethodType = "$ccls/base"; - -struct In_CclsBase : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - - lsTextDocumentPositionParams params; -}; -MAKE_REFLECT_STRUCT(In_CclsBase, id, params); -REGISTER_IN_MESSAGE(In_CclsBase); - -struct Handler_CclsBase : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_CclsBase *request) override { - QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { - return; - } - - WorkingFile *working_file = - working_files->GetFileByFilename(file->def->path); - - Out_LocationList out; - out.id = request->id; - for (SymbolRef sym : - FindSymbolsAtLocation(working_file, file, request->params.position)) { - if (sym.kind == SymbolKind::Type) { - if (const auto *def = db->GetType(sym).AnyDef()) - out.result = GetLsLocationExs(db, working_files, - GetTypeDeclarations(db, def->bases)); - break; - } else if (sym.kind == SymbolKind::Func) { - if (const auto *def = db->GetFunc(sym).AnyDef()) - out.result = GetLsLocationExs(db, working_files, - GetFuncDeclarations(db, def->bases)); - break; - } - } - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsBase); -} // namespace diff --git a/src/messages/ccls_callHierarchy.cc b/src/messages/ccls_call.cc similarity index 83% rename from src/messages/ccls_callHierarchy.cc rename to src/messages/ccls_call.cc index 8b139eb4..0ec68f8b 100644 --- a/src/messages/ccls_callHierarchy.cc +++ b/src/messages/ccls_call.cc @@ -13,17 +13,18 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "hierarchy.hh" #include "message_handler.h" #include "pipeline.hh" -using namespace ccls; #include "query_utils.h" -using namespace ccls; #include +using namespace ccls; + namespace { -MethodType kMethodType = "$ccls/callHierarchy"; +MethodType kMethodType = "$ccls/call"; enum class CallType : uint8_t { Direct = 0, @@ -37,7 +38,7 @@ bool operator&(CallType lhs, CallType rhs) { return uint8_t(lhs) & uint8_t(rhs); } -struct In_CclsCallHierarchy : public RequestInMessage { +struct In_CclsCall : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { @@ -57,15 +58,16 @@ struct In_CclsCallHierarchy : public RequestInMessage { CallType callType = CallType::All; bool qualified = true; int levels = 1; + bool hierarchy = false; }; Params params; }; -MAKE_REFLECT_STRUCT(In_CclsCallHierarchy::Params, textDocument, position, id, - callee, callType, qualified, levels); -MAKE_REFLECT_STRUCT(In_CclsCallHierarchy, id, params); -REGISTER_IN_MESSAGE(In_CclsCallHierarchy); +MAKE_REFLECT_STRUCT(In_CclsCall::Params, textDocument, position, id, + callee, callType, qualified, levels, hierarchy); +MAKE_REFLECT_STRUCT(In_CclsCall, id, params); +REGISTER_IN_MESSAGE(In_CclsCall); -struct Out_CclsCallHierarchy : public lsOutMessage { +struct Out_CclsCall : public lsOutMessage { struct Entry { Usr usr; std::string id; @@ -80,12 +82,12 @@ struct Out_CclsCallHierarchy : public lsOutMessage { lsRequestId id; std::optional result; }; -MAKE_REFLECT_STRUCT(Out_CclsCallHierarchy::Entry, id, name, location, callType, +MAKE_REFLECT_STRUCT(Out_CclsCall::Entry, id, name, location, callType, numChildren, children); -MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsCallHierarchy, jsonrpc, id, +MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsCall, jsonrpc, id, result); -bool Expand(MessageHandler *m, Out_CclsCallHierarchy::Entry *entry, bool callee, +bool Expand(MessageHandler *m, Out_CclsCall::Entry *entry, bool callee, CallType call_type, bool qualified, int levels) { const QueryFunc &func = m->db->Func(entry->usr); const QueryFunc::Def *def = func.AnyDef(); @@ -95,7 +97,7 @@ bool Expand(MessageHandler *m, Out_CclsCallHierarchy::Entry *entry, bool callee, auto handle = [&](Use use, CallType call_type1) { entry->numChildren++; if (levels > 0) { - Out_CclsCallHierarchy::Entry entry1; + Out_CclsCall::Entry entry1; entry1.id = std::to_string(use.usr); entry1.usr = use.usr; if (auto loc = GetLsLocation(m->db, m->working_files, use)) @@ -161,17 +163,17 @@ bool Expand(MessageHandler *m, Out_CclsCallHierarchy::Entry *entry, bool callee, return true; } -struct Handler_CclsCallHierarchy : BaseMessageHandler { +struct Handler_CclsCall : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - std::optional + std::optional BuildInitial(Usr root_usr, bool callee, CallType call_type, bool qualified, int levels) { const auto *def = db->Func(root_usr).AnyDef(); if (!def) return {}; - Out_CclsCallHierarchy::Entry entry; + Out_CclsCall::Entry entry; entry.id = std::to_string(root_usr); entry.usr = root_usr; entry.callType = CallType::Direct; @@ -184,9 +186,9 @@ struct Handler_CclsCallHierarchy : BaseMessageHandler { return entry; } - void Run(In_CclsCallHierarchy *request) override { + void Run(In_CclsCall *request) override { auto ¶ms = request->params; - Out_CclsCallHierarchy out; + Out_CclsCall out; out.id = request->id; if (params.id.size()) { @@ -195,7 +197,7 @@ struct Handler_CclsCallHierarchy : BaseMessageHandler { } catch (...) { return; } - Out_CclsCallHierarchy::Entry entry; + Out_CclsCall::Entry entry; entry.id = std::to_string(params.usr); entry.usr = params.usr; entry.callType = CallType::Direct; @@ -220,9 +222,17 @@ struct Handler_CclsCallHierarchy : BaseMessageHandler { } } - pipeline::WriteStdout(kMethodType, out); + if (params.hierarchy) { + pipeline::WriteStdout(kMethodType, out); + return; + } + Out_LocationList out1; + out1.id = request->id; + if (out.result) + FlattenHierarchy(*out.result, out1); + pipeline::WriteStdout(kMethodType, out1); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsCallHierarchy); +REGISTER_MESSAGE_HANDLER(Handler_CclsCall); } // namespace diff --git a/src/messages/ccls_callers.cc b/src/messages/ccls_callers.cc deleted file mode 100644 index 7b6c28f9..00000000 --- a/src/messages/ccls_callers.cc +++ /dev/null @@ -1,62 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "$ccls/callers"; - -struct In_CclsCallers : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsTextDocumentPositionParams params; -}; -MAKE_REFLECT_STRUCT(In_CclsCallers, id, params); -REGISTER_IN_MESSAGE(In_CclsCallers); - -struct Handler_CclsCallers : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_CclsCallers *request) override { - QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { - return; - } - - WorkingFile *working_file = - working_files->GetFileByFilename(file->def->path); - - Out_LocationList out; - out.id = request->id; - for (SymbolRef sym : - FindSymbolsAtLocation(working_file, file, request->params.position)) { - if (sym.kind == SymbolKind::Func) { - QueryFunc &func = db->GetFunc(sym); - std::vector uses = func.uses; - for (Use func_ref : GetUsesForAllBases(db, func)) - uses.push_back(func_ref); - for (Use func_ref : GetUsesForAllDerived(db, func)) - uses.push_back(func_ref); - out.result = GetLsLocationExs(db, working_files, uses); - break; - } - } - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsCallers); -} // namespace diff --git a/src/messages/ccls_fileInfo.cc b/src/messages/ccls_fileInfo.cc deleted file mode 100644 index 493d7b27..00000000 --- a/src/messages/ccls_fileInfo.cc +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, outline, all_symbols, - skipped_ranges, dependencies); - -namespace { -MethodType kMethodType = "$ccls/fileInfo"; - -struct lsDocumentSymbolParams { - lsTextDocumentIdentifier textDocument; -}; -MAKE_REFLECT_STRUCT(lsDocumentSymbolParams, textDocument); - -struct In_CclsFileInfo : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsDocumentSymbolParams params; -}; -MAKE_REFLECT_STRUCT(In_CclsFileInfo, id, params); -REGISTER_IN_MESSAGE(In_CclsFileInfo); - -struct Out_CclsFileInfo : public lsOutMessage { - lsRequestId id; - QueryFile::Def result; -}; -MAKE_REFLECT_STRUCT(Out_CclsFileInfo, jsonrpc, id, result); - -struct Handler_CclsFileInfo : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_CclsFileInfo *request) override { - QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { - return; - } - - Out_CclsFileInfo out; - out.id = request->id; - // Expose some fields of |QueryFile::Def|. - out.result.path = file->def->path; - out.result.args = file->def->args; - out.result.language = file->def->language; - out.result.includes = file->def->includes; - out.result.skipped_ranges = file->def->skipped_ranges; - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_CclsFileInfo); -} // namespace diff --git a/src/messages/ccls_info.cc b/src/messages/ccls_info.cc new file mode 100644 index 00000000..3efcae50 --- /dev/null +++ b/src/messages/ccls_info.cc @@ -0,0 +1,106 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "message_handler.h" +#include "pipeline.hh" +#include "project.h" +#include "query_utils.h" +using namespace ccls; + +MAKE_REFLECT_STRUCT(QueryFile::Def, path, args, language, skipped_ranges, + dependencies); + +namespace { +MethodType cclsInfo = "$ccls/info", fileInfo = "$ccls/fileInfo"; + +struct In_cclsInfo : public RequestInMessage { + MethodType GetMethodType() const override { return cclsInfo; } +}; +MAKE_REFLECT_STRUCT(In_cclsInfo, id); +REGISTER_IN_MESSAGE(In_cclsInfo); + +struct Out_cclsInfo : public lsOutMessage { + lsRequestId id; + struct Result { + struct DB { + int files, funcs, types, vars; + } db; + struct Pipeline { + int pendingIndexRequests; + } pipeline; + struct Project { + int entries; + } project; + } result; +}; +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result::DB, files, funcs, types, vars); +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result::Pipeline, pendingIndexRequests); +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result::Project, entries); +MAKE_REFLECT_STRUCT(Out_cclsInfo::Result, db, pipeline, project); +MAKE_REFLECT_STRUCT(Out_cclsInfo, jsonrpc, id, result); + +struct Handler_cclsInfo : BaseMessageHandler { + MethodType GetMethodType() const override { return cclsInfo; } + void Run(In_cclsInfo *request) override { + Out_cclsInfo out; + out.id = request->id; + out.result.db.files = db->files.size(); + out.result.db.funcs = db->funcs.size(); + out.result.db.types = db->types.size(); + out.result.db.vars = db->vars.size(); + out.result.pipeline.pendingIndexRequests = pipeline::pending_index_requests; + out.result.project.entries = project->entries.size(); + pipeline::WriteStdout(cclsInfo, out); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_cclsInfo); + +struct In_cclsFileInfo : public RequestInMessage { + MethodType GetMethodType() const override { return fileInfo; } + struct Params { + lsTextDocumentIdentifier textDocument; + } params; +}; +MAKE_REFLECT_STRUCT(In_cclsFileInfo::Params, textDocument); +MAKE_REFLECT_STRUCT(In_cclsFileInfo, id, params); +REGISTER_IN_MESSAGE(In_cclsFileInfo); + +struct Out_cclsFileInfo : public lsOutMessage { + lsRequestId id; + QueryFile::Def result; +}; +MAKE_REFLECT_STRUCT(Out_cclsFileInfo, jsonrpc, id, result); + +struct Handler_cclsFileInfo : BaseMessageHandler { + MethodType GetMethodType() const override { return fileInfo; } + void Run(In_cclsFileInfo *request) override { + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + request->params.textDocument.uri.GetPath(), &file)) + return; + + Out_cclsFileInfo out; + out.id = request->id; + // Expose some fields of |QueryFile::Def|. + out.result.path = file->def->path; + out.result.args = file->def->args; + out.result.language = file->def->language; + out.result.includes = file->def->includes; + out.result.skipped_ranges = file->def->skipped_ranges; + pipeline::WriteStdout(fileInfo, out); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_cclsFileInfo); +} // namespace diff --git a/src/messages/ccls_inheritanceHierarchy.cc b/src/messages/ccls_inheritance.cc similarity index 71% rename from src/messages/ccls_inheritanceHierarchy.cc rename to src/messages/ccls_inheritance.cc index bea19515..0ed23585 100644 --- a/src/messages/ccls_inheritanceHierarchy.cc +++ b/src/messages/ccls_inheritance.cc @@ -13,18 +13,18 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "hierarchy.hh" #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" using namespace ccls; -#include #include namespace { -MethodType kMethodType = "$ccls/inheritanceHierarchy"; +MethodType kMethodType = "$ccls/inheritance"; -struct In_CclsInheritanceHierarchy : public RequestInMessage { +struct In_CclsInheritance : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { // If id+kind are specified, expand a node; otherwise textDocument+position @@ -40,17 +40,17 @@ struct In_CclsInheritanceHierarchy : public RequestInMessage { bool derived = false; bool qualified = true; int levels = 1; - bool flat = false; + bool hierarchy = false; } params; }; -MAKE_REFLECT_STRUCT(In_CclsInheritanceHierarchy::Params, textDocument, position, - id, kind, derived, qualified, levels, flat); -MAKE_REFLECT_STRUCT(In_CclsInheritanceHierarchy, id, params); -REGISTER_IN_MESSAGE(In_CclsInheritanceHierarchy); +MAKE_REFLECT_STRUCT(In_CclsInheritance::Params, textDocument, position, + id, kind, derived, qualified, levels, hierarchy); +MAKE_REFLECT_STRUCT(In_CclsInheritance, id, params); +REGISTER_IN_MESSAGE(In_CclsInheritance); -struct Out_CclsInheritanceHierarchy - : public lsOutMessage { +struct Out_CclsInheritance + : public lsOutMessage { struct Entry { Usr usr; std::string id; @@ -66,16 +66,16 @@ struct Out_CclsInheritanceHierarchy lsRequestId id; std::optional result; }; -MAKE_REFLECT_STRUCT(Out_CclsInheritanceHierarchy::Entry, id, kind, name, +MAKE_REFLECT_STRUCT(Out_CclsInheritance::Entry, id, kind, name, location, numChildren, children); -MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsInheritanceHierarchy, jsonrpc, +MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsInheritance, jsonrpc, id, result); -bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, +bool Expand(MessageHandler *m, Out_CclsInheritance::Entry *entry, bool derived, bool qualified, int levels); template -bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, +bool ExpandHelper(MessageHandler *m, Out_CclsInheritance::Entry *entry, bool derived, bool qualified, int levels, Q &entity) { const auto *def = entity.AnyDef(); if (def) { @@ -83,6 +83,9 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, if (def->spell) { if (auto loc = GetLsLocation(m->db, m->working_files, *def->spell)) entry->location = *loc; + } else if (entity.declarations.size()) { + if (auto loc = GetLsLocation(m->db, m->working_files, entity.declarations[0])) + entry->location = *loc; } } else if (!derived) { entry->numChildren = 0; @@ -94,7 +97,7 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, for (auto usr : entity.derived) { if (!seen.insert(usr).second) continue; - Out_CclsInheritanceHierarchy::Entry entry1; + Out_CclsInheritance::Entry entry1; entry1.id = std::to_string(usr); entry1.usr = usr; entry1.kind = entry->kind; @@ -109,7 +112,7 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, for (auto usr : def->bases) { if (!seen.insert(usr).second) continue; - Out_CclsInheritanceHierarchy::Entry entry1; + Out_CclsInheritance::Entry entry1; entry1.id = std::to_string(usr); entry1.usr = usr; entry1.kind = entry->kind; @@ -123,7 +126,7 @@ bool ExpandHelper(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, return true; } -bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, +bool Expand(MessageHandler *m, Out_CclsInheritance::Entry *entry, bool derived, bool qualified, int levels) { if (entry->kind == SymbolKind::Func) return ExpandHelper(m, entry, derived, qualified, levels, @@ -133,13 +136,13 @@ bool Expand(MessageHandler *m, Out_CclsInheritanceHierarchy::Entry *entry, m->db->Type(entry->usr)); } -struct Handler_CclsInheritanceHierarchy - : BaseMessageHandler { +struct Handler_CclsInheritance + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - std::optional + std::optional BuildInitial(SymbolRef sym, bool derived, bool qualified, int levels) { - Out_CclsInheritanceHierarchy::Entry entry; + Out_CclsInheritance::Entry entry; entry.id = std::to_string(sym.usr); entry.usr = sym.usr; entry.kind = sym.kind; @@ -147,18 +150,18 @@ struct Handler_CclsInheritanceHierarchy return entry; } - void Run(In_CclsInheritanceHierarchy *request) override { + void Run(In_CclsInheritance *request) override { auto ¶ms = request->params; - Out_CclsInheritanceHierarchy out; + Out_CclsInheritance out; out.id = request->id; - if (!params.flat && params.id.size()) { + if (params.id.size()) { try { params.usr = std::stoull(params.id); } catch (...) { return; } - Out_CclsInheritanceHierarchy::Entry entry; + Out_CclsInheritance::Entry entry; entry.id = std::to_string(params.usr); entry.usr = params.usr; entry.kind = params.kind; @@ -181,31 +184,17 @@ struct Handler_CclsInheritanceHierarchy } } - if (!params.flat) { + if (params.hierarchy) { pipeline::WriteStdout(kMethodType, out); return; } Out_LocationList out1; out1.id = request->id; - if (out.result) { - std::queue q; - for (auto &entry1 : out.result->children) - q.push(&entry1); - while (q.size()) { - auto *entry = q.front(); - q.pop(); - if (entry->location.uri.raw_uri.size()) - out1.result.push_back({entry->location}); - for (auto &entry1 : entry->children) - q.push(&entry1); - } - std::sort(out1.result.begin(), out1.result.end()); - out1.result.erase(std::unique(out1.result.begin(), out1.result.end()), - out1.result.end()); - } + if (out.result) + FlattenHierarchy(*out.result, out1); pipeline::WriteStdout(kMethodType, out1); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsInheritanceHierarchy); +REGISTER_MESSAGE_HANDLER(Handler_CclsInheritance); } // namespace diff --git a/src/messages/ccls_memberHierarchy.cc b/src/messages/ccls_member.cc similarity index 50% rename from src/messages/ccls_memberHierarchy.cc rename to src/messages/ccls_member.cc index 7de03d9e..47241aad 100644 --- a/src/messages/ccls_memberHierarchy.cc +++ b/src/messages/ccls_member.cc @@ -13,21 +13,24 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "clang_tu.hh" +#include "hierarchy.hh" #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; #include -using namespace clang; +#include -#include #include -namespace { -MethodType kMethodType = "$ccls/memberHierarchy"; +using namespace ccls; +using namespace clang; -struct In_CclsMemberHierarchy : public RequestInMessage { +namespace { +MethodType kMethodType = "$ccls/member"; + +struct In_CclsMember : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { @@ -42,16 +45,19 @@ struct In_CclsMemberHierarchy : public RequestInMessage { bool qualified = false; int levels = 1; - bool flat = false; + // If SymbolKind::Func and the point is at a type, list member functions + // instead of member variables. + SymbolKind kind = SymbolKind::Var; + bool hierarchy = false; } params; }; -MAKE_REFLECT_STRUCT(In_CclsMemberHierarchy::Params, textDocument, position, id, - qualified, levels, flat); -MAKE_REFLECT_STRUCT(In_CclsMemberHierarchy, id, params); -REGISTER_IN_MESSAGE(In_CclsMemberHierarchy); +MAKE_REFLECT_STRUCT(In_CclsMember::Params, textDocument, position, id, + qualified, levels, kind, hierarchy); +MAKE_REFLECT_STRUCT(In_CclsMember, id, params); +REGISTER_IN_MESSAGE(In_CclsMember); -struct Out_CclsMemberHierarchy : public lsOutMessage { +struct Out_CclsMember : public lsOutMessage { struct Entry { Usr usr; std::string id; @@ -67,21 +73,21 @@ struct Out_CclsMemberHierarchy : public lsOutMessage { lsRequestId id; std::optional result; }; -MAKE_REFLECT_STRUCT(Out_CclsMemberHierarchy::Entry, id, name, fieldName, +MAKE_REFLECT_STRUCT(Out_CclsMember::Entry, id, name, fieldName, location, numChildren, children); -MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsMemberHierarchy, jsonrpc, id, +MAKE_REFLECT_STRUCT_MANDATORY_OPTIONAL(Out_CclsMember, jsonrpc, id, result); -bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, - bool qualified, int levels); +bool Expand(MessageHandler *m, Out_CclsMember::Entry *entry, + bool qualified, int levels, SymbolKind memberKind); // Add a field to |entry| which is a Func/Type. -void DoField(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, +void DoField(MessageHandler *m, Out_CclsMember::Entry *entry, const QueryVar &var, int64_t offset, bool qualified, int levels) { const QueryVar::Def *def1 = var.AnyDef(); if (!def1) return; - Out_CclsMemberHierarchy::Entry entry1; + Out_CclsMember::Entry entry1; // With multiple inheritance, the offset is incorrect. if (offset >= 0) { if (offset / 8 < 10) @@ -108,7 +114,7 @@ void DoField(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, if (def1->type) { entry1.id = std::to_string(def1->type); entry1.usr = def1->type; - if (Expand(m, &entry1, qualified, levels)) + if (Expand(m, &entry1, qualified, levels, SymbolKind::Var)) entry->children.push_back(std::move(entry1)); } else { entry1.id = "0"; @@ -118,14 +124,14 @@ void DoField(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, } // Expand a type node by adding members recursively to it. -bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, - bool qualified, int levels) { +bool Expand(MessageHandler *m, Out_CclsMember::Entry *entry, + bool qualified, int levels, SymbolKind memberKind) { if (0 < entry->usr && entry->usr <= BuiltinType::LastKind) { entry->name = ClangBuiltinTypeName(int(entry->usr)); return true; } - const QueryType &type = m->db->Type(entry->usr); - const QueryType::Def *def = type.AnyDef(); + const QueryType *type = &m->db->Type(entry->usr); + const QueryType::Def *def = type->AnyDef(); // builtin types have no declaration and empty |qualified|. if (!def) return false; @@ -133,51 +139,97 @@ bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, std::unordered_set seen; if (levels > 0) { std::vector stack; - seen.insert(type.usr); - stack.push_back(&type); + seen.insert(type->usr); + stack.push_back(type); while (stack.size()) { - const auto *def = stack.back()->AnyDef(); + type = stack.back(); stack.pop_back(); - if (def) { - EachDefinedType(m->db, def->bases, [&](QueryType &type1) { - if (!seen.count(type1.usr)) { - seen.insert(type1.usr); - stack.push_back(&type1); - } - }); - if (def->alias_of) { - const QueryType::Def *def1 = m->db->Type(def->alias_of).AnyDef(); - Out_CclsMemberHierarchy::Entry entry1; - entry1.id = std::to_string(def->alias_of); - entry1.usr = def->alias_of; - if (def1 && def1->spell) { - // The declaration of target type. - if (std::optional loc = - GetLsLocation(m->db, m->working_files, *def1->spell)) - entry1.location = *loc; - } else if (def->spell) { - // Builtin types have no declaration but the typedef declaration - // itself is useful. - if (std::optional loc = - GetLsLocation(m->db, m->working_files, *def->spell)) - entry1.location = *loc; - } - if (def1 && qualified) - entry1.fieldName = def1->detailed_name; - if (Expand(m, &entry1, qualified, levels - 1)) { - // For builtin types |name| is set. - if (entry1.fieldName.empty()) - entry1.fieldName = std::string(entry1.name); - entry->children.push_back(std::move(entry1)); - } - } else { - for (auto it : def->vars) { - QueryVar &var = m->db->Var(it.first); - if (!var.def.empty()) - DoField(m, entry, var, it.second, qualified, levels - 1); - } + const auto *def = type->AnyDef(); + if (!def) continue; + for (Usr usr : def->bases) { + auto &type1 = m->db->Type(usr); + if (type1.def.size()) { + seen.insert(type1.usr); + stack.push_back(&type1); } } + if (def->alias_of) { + const QueryType::Def *def1 = m->db->Type(def->alias_of).AnyDef(); + Out_CclsMember::Entry entry1; + entry1.id = std::to_string(def->alias_of); + entry1.usr = def->alias_of; + if (def1 && def1->spell) { + // The declaration of target type. + if (std::optional loc = + GetLsLocation(m->db, m->working_files, *def1->spell)) + entry1.location = *loc; + } else if (def->spell) { + // Builtin types have no declaration but the typedef declaration + // itself is useful. + if (std::optional loc = + GetLsLocation(m->db, m->working_files, *def->spell)) + entry1.location = *loc; + } + if (def1 && qualified) + entry1.fieldName = def1->detailed_name; + if (Expand(m, &entry1, qualified, levels - 1, memberKind)) { + // For builtin types |name| is set. + if (entry1.fieldName.empty()) + entry1.fieldName = std::string(entry1.name); + entry->children.push_back(std::move(entry1)); + } + } else if (memberKind == SymbolKind::Func) { + llvm::DenseSet seen1; + for (auto &def : type->def) + for (Usr usr : def.funcs) + if (seen1.insert(usr).second) { + QueryFunc &func1 = m->db->Func(usr); + if (const QueryFunc::Def *def1 = func1.AnyDef()) { + Out_CclsMember::Entry entry1; + entry1.fieldName = def1->Name(false); + if (def1->spell) { + if (auto loc = + GetLsLocation(m->db, m->working_files, *def1->spell)) + entry1.location = *loc; + } else if (func1.declarations.size()) { + if (auto loc = GetLsLocation(m->db, m->working_files, + func1.declarations[0])) + entry1.location = *loc; + } + entry->children.push_back(std::move(entry1)); + } + } + } else if (memberKind == SymbolKind::Type) { + llvm::DenseSet seen1; + for (auto &def : type->def) + for (Usr usr : def.types) + if (seen1.insert(usr).second) { + QueryType &type1 = m->db->Type(usr); + if (const QueryType::Def *def1 = type1.AnyDef()) { + Out_CclsMember::Entry entry1; + entry1.fieldName = def1->Name(false); + if (def1->spell) { + if (auto loc = + GetLsLocation(m->db, m->working_files, *def1->spell)) + entry1.location = *loc; + } else if (type1.declarations.size()) { + if (auto loc = GetLsLocation(m->db, m->working_files, + type1.declarations[0])) + entry1.location = *loc; + } + entry->children.push_back(std::move(entry1)); + } + } + } else { + llvm::DenseSet seen1; + for (auto &def : type->def) + for (auto it : def.vars) + if (seen1.insert(it.first).second) { + QueryVar &var = m->db->Var(it.first); + if (!var.def.empty()) + DoField(m, entry, var, it.second, qualified, levels - 1); + } + } } entry->numChildren = int(entry->children.size()); } else @@ -185,12 +237,12 @@ bool Expand(MessageHandler *m, Out_CclsMemberHierarchy::Entry *entry, return true; } -struct Handler_CclsMemberHierarchy - : BaseMessageHandler { +struct Handler_CclsMember + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - std::optional - BuildInitial(SymbolKind kind, Usr root_usr, bool qualified, int levels) { + std::optional + BuildInitial(SymbolKind kind, Usr root_usr, bool qualified, int levels, SymbolKind memberKind) { switch (kind) { default: return {}; @@ -199,7 +251,7 @@ struct Handler_CclsMemberHierarchy if (!def) return {}; - Out_CclsMemberHierarchy::Entry entry; + Out_CclsMember::Entry entry; // Not type, |id| is invalid. entry.name = def->Name(qualified); if (def->spell) { @@ -207,9 +259,11 @@ struct Handler_CclsMemberHierarchy GetLsLocation(db, working_files, *def->spell)) entry.location = *loc; } - EachDefinedVar(db, def->vars, [&](QueryVar &var) { - DoField(this, &entry, var, -1, qualified, levels - 1); - }); + for (Usr usr : def->vars) { + auto &var = db->Var(usr); + if (var.def.size()) + DoField(this, &entry, var, -1, qualified, levels - 1); + } return entry; } case SymbolKind::Type: { @@ -217,7 +271,7 @@ struct Handler_CclsMemberHierarchy if (!def) return {}; - Out_CclsMemberHierarchy::Entry entry; + Out_CclsMember::Entry entry; entry.id = std::to_string(root_usr); entry.usr = root_usr; if (def->spell) { @@ -225,15 +279,15 @@ struct Handler_CclsMemberHierarchy GetLsLocation(db, working_files, *def->spell)) entry.location = *loc; } - Expand(this, &entry, qualified, levels); + Expand(this, &entry, qualified, levels, memberKind); return entry; } } } - void Run(In_CclsMemberHierarchy *request) override { + void Run(In_CclsMember *request) override { auto ¶ms = request->params; - Out_CclsMemberHierarchy out; + Out_CclsMember out; out.id = request->id; if (params.id.size()) { @@ -242,12 +296,12 @@ struct Handler_CclsMemberHierarchy } catch (...) { return; } - Out_CclsMemberHierarchy::Entry entry; + Out_CclsMember::Entry entry; entry.id = std::to_string(params.usr); entry.usr = params.usr; // entry.name is empty as it is known by the client. if (db->HasType(entry.usr) && - Expand(this, &entry, params.qualified, params.levels)) + Expand(this, &entry, params.qualified, params.levels, params.kind)) out.result = std::move(entry); } else { QueryFile *file; @@ -260,14 +314,14 @@ struct Handler_CclsMemberHierarchy switch (sym.kind) { case SymbolKind::Func: case SymbolKind::Type: - out.result = - BuildInitial(sym.kind, sym.usr, params.qualified, params.levels); + out.result = BuildInitial(sym.kind, sym.usr, params.qualified, + params.levels, params.kind); break; case SymbolKind::Var: { const QueryVar::Def *def = db->GetVar(sym).AnyDef(); if (def && def->type) out.result = BuildInitial(SymbolKind::Type, def->type, - params.qualified, params.levels); + params.qualified, params.levels, params.kind); break; } default: @@ -277,31 +331,17 @@ struct Handler_CclsMemberHierarchy } } - if (!params.flat) { + if (params.hierarchy) { pipeline::WriteStdout(kMethodType, out); return; } Out_LocationList out1; out1.id = request->id; - if (out.result) { - std::queue q; - for (auto &entry1 : out.result->children) - q.push(&entry1); - while (q.size()) { - auto *entry = q.front(); - q.pop(); - if (entry->location.uri.raw_uri.size()) - out1.result.push_back({entry->location}); - for (auto &entry1 : entry->children) - q.push(&entry1); - } - std::sort(out1.result.begin(), out1.result.end()); - out1.result.erase(std::unique(out1.result.begin(), out1.result.end()), - out1.result.end()); - } + if (out.result) + FlattenHierarchy(*out.result, out1); pipeline::WriteStdout(kMethodType, out1); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsMemberHierarchy); +REGISTER_MESSAGE_HANDLER(Handler_CclsMember); } // namespace diff --git a/src/messages/ccls_navigate.cc b/src/messages/ccls_navigate.cc new file mode 100644 index 00000000..921ffae1 --- /dev/null +++ b/src/messages/ccls_navigate.cc @@ -0,0 +1,115 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "message_handler.h" +#include "pipeline.hh" +#include "query_utils.h" +using namespace ccls; + +namespace { +MethodType kMethodType = "$ccls/navigate"; + +struct In_CclsNavigate : public RequestInMessage { + MethodType GetMethodType() const override { return kMethodType; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsPosition position; + std::string direction; + } params; +}; +MAKE_REFLECT_STRUCT(In_CclsNavigate::Params, textDocument, position, direction); +MAKE_REFLECT_STRUCT(In_CclsNavigate, id, params); +REGISTER_IN_MESSAGE(In_CclsNavigate); + +struct Handler_CclsNavigate : BaseMessageHandler { + MethodType GetMethodType() const override { return kMethodType; } + void Run(In_CclsNavigate *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + + WorkingFile *wfile = + working_files->GetFileByFilename(file->def->path); + lsPosition ls_pos = request->params.position; + if (wfile && wfile->index_lines.size()) + if (auto line = wfile->GetIndexPosFromBufferPos( + ls_pos.line, &ls_pos.character, false)) + ls_pos.line = *line; + Position pos{(int16_t)ls_pos.line, (int16_t)ls_pos.character}; + + Maybe res; + switch (params.direction[0]) { + case 'D': { + Maybe parent; + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end && + (!parent || parent->start < sym.range.start)) + parent = sym.range; + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && pos < sym.range.start && + (!parent || sym.range.end <= parent->end) && + (!res || sym.range.start < res->start)) + res = sym.range; + break; + } + case 'L': + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.end <= pos && + (!res || (res->end == sym.range.end ? sym.range.start < res->start + : res->end < sym.range.end))) + res = sym.range; + break; + case 'R': { + Maybe parent; + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.start <= pos && pos < sym.range.end && + (!parent || parent->start < sym.range.start)) + parent = sym.range; + if (parent && parent->start.line == pos.line && pos < parent->end) { + pos = parent->end; + if (pos.column) + pos.column--; + } + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && pos < sym.range.start && + (!res || + (sym.range.start == res->start ? res->end < sym.range.end + : sym.range.start < res->start))) + res = sym.range; + break; + } + case 'U': + default: + for (auto [sym, refcnt] : file->outline2refcnt) + if (refcnt > 0 && sym.range.start < pos && pos < sym.range.end && + (!res || res->start < sym.range.start)) + res = sym.range; + break; + } + Out_LocationList out; + out.id = request->id; + if (res) + if (auto ls_range = GetLsRange(wfile, *res)) { + lsLocationEx &ls_loc = out.result.emplace_back(); + ls_loc.uri = params.textDocument.uri; + ls_loc.range = *ls_range; + } + pipeline::WriteStdout(kMethodType, out); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_CclsNavigate); +} // namespace diff --git a/src/messages/ccls_freshenIndex.cc b/src/messages/ccls_reload.cc similarity index 71% rename from src/messages/ccls_freshenIndex.cc rename to src/messages/ccls_reload.cc index edf23b4d..67b97c25 100644 --- a/src/messages/ccls_freshenIndex.cc +++ b/src/messages/ccls_reload.cc @@ -13,38 +13,49 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "clang_complete.hh" #include "match.h" #include "message_handler.h" #include "pipeline.hh" -#include "platform.h" #include "project.h" #include "working_files.h" -using namespace ccls; #include #include -namespace { -MethodType kMethodType = "$ccls/freshenIndex"; +using namespace ccls; -struct In_CclsFreshenIndex : public NotificationInMessage { +namespace { +MethodType kMethodType = "$ccls/reload"; + +struct In_CclsReload : public NotificationInMessage { MethodType GetMethodType() const override { return kMethodType; } struct Params { bool dependencies = true; std::vector whitelist; std::vector blacklist; - }; - Params params; + } params; }; -MAKE_REFLECT_STRUCT(In_CclsFreshenIndex::Params, dependencies, whitelist, +MAKE_REFLECT_STRUCT(In_CclsReload::Params, dependencies, whitelist, blacklist); -MAKE_REFLECT_STRUCT(In_CclsFreshenIndex, params); -REGISTER_IN_MESSAGE(In_CclsFreshenIndex); +MAKE_REFLECT_STRUCT(In_CclsReload, params); +REGISTER_IN_MESSAGE(In_CclsReload); -struct Handler_CclsFreshenIndex : BaseMessageHandler { +struct Handler_CclsReload : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - void Run(In_CclsFreshenIndex *request) override { - GroupMatch matcher(request->params.whitelist, request->params.blacklist); + void Run(In_CclsReload *request) override { + const auto ¶ms = request->params; + // Send index requests for every file. + if (params.whitelist.empty() && params.blacklist.empty()) { + vfs->Clear(); + db->clear(); + project->Index(working_files, lsRequestId()); + clang_complete->FlushAllSessions(); + return; + } + + // TODO + GroupMatch matcher(params.whitelist, params.blacklist); std::queue q; // |need_index| stores every filename ever enqueued. @@ -69,16 +80,6 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler { q.pop(); need_index.insert(file->def->path); - std::optional write_time = LastWriteTime(file->def->path); - if (!write_time) - continue; - { - std::lock_guard lock(vfs->mutex); - VFS::State &st = vfs->state[file->def->path]; - if (st.timestamp < write_time) - st.stage = 0; - } - if (request->params.dependencies) for (const std::string &path : graph[file->def->path]) { auto it = path_to_file.find(path); @@ -88,10 +89,7 @@ struct Handler_CclsFreshenIndex : BaseMessageHandler { } } } - - // Send index requests for every file. - project->Index(working_files, lsRequestId()); } }; -REGISTER_MESSAGE_HANDLER(Handler_CclsFreshenIndex); +REGISTER_MESSAGE_HANDLER(Handler_CclsReload); } // namespace diff --git a/src/messages/initialize.cc b/src/messages/initialize.cc index b687b6a9..443bf6a6 100644 --- a/src/messages/initialize.cc +++ b/src/messages/initialize.cc @@ -13,6 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +#include "clang_complete.hh" #include "filesystem.hh" #include "include_complete.h" #include "log.hh" @@ -22,16 +23,16 @@ limitations under the License. #include "project.h" #include "serializers/json.h" #include "working_files.h" -using namespace ccls; #include #include -using namespace llvm; -#include #include #include +using namespace ccls; +using namespace llvm; + // TODO Cleanup global variables extern std::string g_init_options; @@ -65,7 +66,7 @@ MAKE_REFLECT_STRUCT(lsCompletionOptions, resolveProvider, triggerCharacters); // Format document on type options struct lsDocumentOnTypeFormattingOptions { // A character on which formatting should be triggered, like `}`. - std::string firstTriggerCharacter; + std::string firstTriggerCharacter = "}"; // More trigger characters. std::vector moreTriggerCharacter; @@ -76,17 +77,10 @@ MAKE_REFLECT_STRUCT(lsDocumentOnTypeFormattingOptions, firstTriggerCharacter, // Document link options struct lsDocumentLinkOptions { // Document links have a resolve provider as well. - bool resolveProvider = true; + bool resolveProvider = false; }; MAKE_REFLECT_STRUCT(lsDocumentLinkOptions, resolveProvider); -// Execute command options. -struct lsExecuteCommandOptions { - // The commands to be executed on the server - std::vector commands; -}; -MAKE_REFLECT_STRUCT(lsExecuteCommandOptions, commands); - // Save options. struct lsSaveOptions { // The client is supposed to include the content on save. @@ -169,19 +163,21 @@ struct lsServerCapabilities { // The server provides code lens. lsCodeLensOptions codeLensProvider; // The server provides document formatting. - bool documentFormattingProvider = false; + bool documentFormattingProvider = true; // The server provides document range formatting. - bool documentRangeFormattingProvider = false; + bool documentRangeFormattingProvider = true; // The server provides document formatting on typing. - std::optional - documentOnTypeFormattingProvider; + lsDocumentOnTypeFormattingOptions documentOnTypeFormattingProvider; // The server provides rename support. bool renameProvider = true; // The server provides document link support. lsDocumentLinkOptions documentLinkProvider; // The server provides execute command support. - lsExecuteCommandOptions executeCommandProvider; + struct ExecuteCommandOptions { + std::vector commands{std::string(ccls_xref)}; + } executeCommandProvider; }; +MAKE_REFLECT_STRUCT(lsServerCapabilities::ExecuteCommandOptions, commands); MAKE_REFLECT_STRUCT(lsServerCapabilities, textDocumentSync, hoverProvider, completionProvider, signatureHelpProvider, definitionProvider, implementationProvider, @@ -269,6 +265,10 @@ struct lsTextDocumentClientCapabilities { } completionItem; } completion; + struct lsDocumentSymbol { + bool hierarchicalDocumentSymbolSupport = false; + } documentSymbol; + struct lsGenericDynamicReg { // Whether foo supports dynamic registration. std::optional dynamicRegistration; @@ -290,6 +290,8 @@ MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsSynchronization, dynamicRegistration, willSave, willSaveWaitUntil, didSave); MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsCompletion, dynamicRegistration, completionItem); +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsDocumentSymbol, + hierarchicalDocumentSymbolSupport); MAKE_REFLECT_STRUCT( lsTextDocumentClientCapabilities::lsCompletion::lsCompletionItem, snippetSupport); @@ -298,8 +300,8 @@ MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities::lsGenericDynamicReg, MAKE_REFLECT_STRUCT( lsTextDocumentClientCapabilities::CodeLensRegistrationOptions, dynamicRegistration, resolveProvider); -MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, synchronization, - completion, rename); +MAKE_REFLECT_STRUCT(lsTextDocumentClientCapabilities, completion, + documentSymbol, rename, synchronization); struct lsClientCapabilities { // Workspace specific client capabilities. @@ -438,10 +440,7 @@ struct Handler_Initialize : BaseMessageHandler { Reflect(json_writer, *g_config); LOG_S(INFO) << "initializationOptions: " << output.GetString(); - if (g_config->cacheDirectory.empty()) { - LOG_S(ERROR) << "cacheDirectory cannot be empty."; - exit(1); - } else { + if (g_config->cacheDirectory.size()) { g_config->cacheDirectory = NormalizePath(g_config->cacheDirectory); EnsureEndsInSlash(g_config->cacheDirectory); } @@ -449,12 +448,15 @@ struct Handler_Initialize : BaseMessageHandler { // Client capabilities const auto &capabilities = params.capabilities; - g_config->client.snippetSupport = + g_config->client.snippetSupport &= capabilities.textDocument.completion.completionItem.snippetSupport; + g_config->client.hierarchicalDocumentSymbolSupport &= + capabilities.textDocument.documentSymbol.hierarchicalDocumentSymbolSupport; // Ensure there is a resource directory. if (g_config->clang.resourceDir.empty()) g_config->clang.resourceDir = GetDefaultResourceDirectory(); + DoPathMapping(g_config->clang.resourceDir); LOG_S(INFO) << "Using -resource-dir=" << g_config->clang.resourceDir; // Send initialization before starting indexers, so we don't send a @@ -470,15 +472,16 @@ struct Handler_Initialize : BaseMessageHandler { // Set project root. EnsureEndsInSlash(project_path); g_config->projectRoot = project_path; - // Create two cache directories for files inside and outside of the - // project. - sys::fs::create_directories(g_config->cacheDirectory + - EscapeFileName(g_config->projectRoot)); - sys::fs::create_directories(g_config->cacheDirectory + '@' + - EscapeFileName(g_config->projectRoot)); + if (g_config->cacheDirectory.size()) { + // Create two cache directories for files inside and outside of the + // project. + auto len = g_config->projectRoot.size(); + std::string escaped = EscapeFileName(g_config->projectRoot.substr(0, len - 1)); + sys::fs::create_directories(g_config->cacheDirectory + escaped); + sys::fs::create_directories(g_config->cacheDirectory + '@' + escaped); + } - diag_pub->Init(); - semantic_cache->Init(); + idx::Init(); // Open up / load the project. project->Load(project_path); @@ -492,10 +495,9 @@ struct Handler_Initialize : BaseMessageHandler { LOG_S(INFO) << "start " << g_config->index.threads << " indexers"; for (int i = 0; i < g_config->index.threads; i++) { std::thread([=]() { - g_thread_id = i + 1; std::string name = "indexer" + std::to_string(i); set_thread_name(name.c_str()); - pipeline::Indexer_Main(diag_pub, vfs, project, working_files); + pipeline::Indexer_Main(clang_complete, vfs, project, working_files); }) .detach(); } diff --git a/src/messages/textDocument_codeAction.cc b/src/messages/textDocument_codeAction.cc index 9ee4e5e1..ac5564b3 100644 --- a/src/messages/textDocument_codeAction.cc +++ b/src/messages/textDocument_codeAction.cc @@ -18,12 +18,6 @@ limitations under the License. #include "working_files.h" using namespace ccls; -struct CommandArgs { - lsDocumentUri textDocumentUri; - std::vector edits; -}; -MAKE_REFLECT_STRUCT_WRITER_AS_ARRAY(CommandArgs, textDocumentUri, edits); - namespace { MethodType kMethodType = "textDocument/codeAction"; @@ -53,10 +47,17 @@ MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction::lsCodeActionParams, textDocument, MAKE_REFLECT_STRUCT(In_TextDocumentCodeAction, id, params); REGISTER_IN_MESSAGE(In_TextDocumentCodeAction); +struct lsCodeAction { + std::string title; + const char *kind = "quickfix"; + lsWorkspaceEdit edit; +}; +MAKE_REFLECT_STRUCT(lsCodeAction, title, kind, edit); + struct Out_TextDocumentCodeAction : public lsOutMessage { lsRequestId id; - std::vector> result; + std::vector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentCodeAction, jsonrpc, id, result); @@ -76,12 +77,12 @@ struct Handler_TextDocumentCodeAction working_files->DoAction([&]() { diagnostics = wfile->diagnostics_; }); for (lsDiagnostic &diag : diagnostics) if (diag.fixits_.size()) { - lsCommand command; - command.title = "FixIt: " + diag.message; - command.command = "ccls._applyFixIt"; - command.arguments.textDocumentUri = params.textDocument.uri; - command.arguments.edits = diag.fixits_; - out.result.push_back(command); + lsCodeAction &cmd = out.result.emplace_back(); + cmd.title = "FixIt: " + diag.message; + auto &edit = cmd.edit.documentChanges.emplace_back(); + edit.textDocument.uri = params.textDocument.uri; + edit.textDocument.version = wfile->version; + edit.edits = diag.fixits_; } pipeline::WriteStdout(kMethodType, out); } diff --git a/src/messages/textDocument_codeLens.cc b/src/messages/textDocument_codeLens.cc index e28928e4..da64859e 100644 --- a/src/messages/textDocument_codeLens.cc +++ b/src/messages/textDocument_codeLens.cc @@ -13,204 +13,154 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" -#include "lsp_code_action.h" #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" +#include "serializers/json.h" + +#include + +#include + using namespace ccls; namespace { -MethodType kMethodType = "textDocument/codeLens"; +const MethodType codeLens = "textDocument/codeLens", + executeCommand = "workspace/executeCommand"; -struct lsDocumentCodeLensParams { - lsTextDocumentIdentifier textDocument; +struct lsCommand { + std::string title; + std::string command; + std::vector arguments; +}; +MAKE_REFLECT_STRUCT(lsCommand, title, command, arguments); + +struct lsCodeLens { + lsRange range; + std::optional command; +}; +MAKE_REFLECT_STRUCT(lsCodeLens, range, command); + +struct Cmd_xref { + Usr usr; + SymbolKind kind; + std::string field; +}; +MAKE_REFLECT_STRUCT(Cmd_xref, usr, kind, field); + +struct Out_xref : public lsOutMessage { + lsRequestId id; + std::vector result; +}; +MAKE_REFLECT_STRUCT(Out_xref, jsonrpc, id, result); + +template +std::string ToString(T &v) { + rapidjson::StringBuffer output; + rapidjson::Writer writer(output); + JsonWriter json_writer(&writer); + Reflect(json_writer, v); + return output.GetString(); +} + +struct CommonCodeLensParams { + std::vector *result; + DB *db; + WorkingFile *wfile; }; -MAKE_REFLECT_STRUCT(lsDocumentCodeLensParams, textDocument); -using TCodeLens = lsCodeLens; struct In_TextDocumentCodeLens : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsDocumentCodeLensParams params; + MethodType GetMethodType() const override { return codeLens; } + struct Params { + lsTextDocumentIdentifier textDocument; + } params; }; +MAKE_REFLECT_STRUCT(In_TextDocumentCodeLens::Params, textDocument); MAKE_REFLECT_STRUCT(In_TextDocumentCodeLens, id, params); REGISTER_IN_MESSAGE(In_TextDocumentCodeLens); struct Out_TextDocumentCodeLens : public lsOutMessage { lsRequestId id; - std::vector> - result; + std::vector result; }; MAKE_REFLECT_STRUCT(Out_TextDocumentCodeLens, jsonrpc, id, result); -struct CommonCodeLensParams { - std::vector *result; - DB *db; - WorkingFiles *working_files; - WorkingFile *working_file; -}; - -Use OffsetStartColumn(Use use, int16_t offset) { - use.range.start.column += offset; - return use; -} - -void AddCodeLens(const char *singular, const char *plural, - CommonCodeLensParams *common, Use use, - const std::vector &uses, bool force_display) { - TCodeLens code_lens; - std::optional range = GetLsRange(common->working_file, use.range); - if (!range) - return; - if (use.file_id < 0) - return; - code_lens.range = *range; - code_lens.command = lsCommand(); - code_lens.command->command = "ccls.showReferences"; - code_lens.command->arguments.uri = GetLsDocumentUri(common->db, use.file_id); - code_lens.command->arguments.position = code_lens.range.start; - - // Add unique uses. - std::vector unique_uses; - for (Use use1 : uses) { - if (auto ls_loc = GetLsLocation(common->db, common->working_files, use1)) - unique_uses.push_back(*ls_loc); - } - code_lens.command->arguments.locations.assign(unique_uses.begin(), - unique_uses.end()); - - // User visible label - size_t num_usages = unique_uses.size(); - code_lens.command->title = std::to_string(num_usages) + " "; - if (num_usages == 1) - code_lens.command->title += singular; - else - code_lens.command->title += plural; - - if (force_display || unique_uses.size() > 0) - common->result->push_back(code_lens); -} - struct Handler_TextDocumentCodeLens : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } + MethodType GetMethodType() const override { return codeLens; } void Run(In_TextDocumentCodeLens *request) override { + auto ¶ms = request->params; Out_TextDocumentCodeLens out; out.id = request->id; - - lsDocumentUri file_as_uri = request->params.textDocument.uri; - std::string path = file_as_uri.GetPath(); - - clang_complete->NotifyView(path); + std::string path = params.textDocument.uri.GetPath(); QueryFile *file; - if (!FindFileOrFail(db, project, request->id, - request->params.textDocument.uri.GetPath(), &file)) { + if (!FindFileOrFail(db, project, request->id, path, &file)) return; - } + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); - CommonCodeLensParams common; - common.result = &out.result; - common.db = db; - common.working_files = working_files; - common.working_file = working_files->GetFileByFilename(file->def->path); + auto Add = [&](const char *singular, Cmd_xref show, Use use, int num, + bool force_display = false) { + if (!num && !force_display) + return; + std::optional range = GetLsRange(wfile, use.range); + if (!range) + return; + lsCodeLens &code_lens = out.result.emplace_back(); + code_lens.range = *range; + code_lens.command = lsCommand(); + code_lens.command->command = std::string(ccls_xref); + bool plural = num > 1 && singular[strlen(singular) - 1] != 'd'; + code_lens.command->title = + llvm::formatv("{0} {1}{2}", num, singular, plural ? "s" : "").str(); + code_lens.command->arguments.push_back(ToString(show)); + }; - for (SymbolRef sym : file->def->outline) { - // NOTE: We OffsetColumn so that the code lens always show up in a - // predictable order. Otherwise, the client may randomize it. - Use use{{sym.range, sym.usr, sym.kind, sym.role}, file->id}; + auto ToSpell = [&](Use use) { + Maybe def = GetDefinitionSpell(db, use); + if (def && def->file_id == use.file_id && + def->range.start.line == use.range.start.line) + return *def; + return use; + }; + std::unordered_set seen; + for (auto [sym, refcnt] : file->outline2refcnt) { + if (refcnt <= 0 || !seen.insert(sym.range).second) + continue; + Use use = ToSpell({{sym.range, sym.usr, sym.kind, sym.role}, file->id}); switch (sym.kind) { - case SymbolKind::Type: { - QueryType &type = db->GetType(sym); - const QueryType::Def *def = type.AnyDef(); - if (!def || def->kind == lsSymbolKind::Namespace) - continue; - AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0), - type.uses, true /*force_display*/); - AddCodeLens("derived", "derived", &common, OffsetStartColumn(use, 1), - GetTypeDeclarations(db, type.derived), - false /*force_display*/); - AddCodeLens("var", "vars", &common, OffsetStartColumn(use, 2), - GetVarDeclarations(db, type.instances, true), - false /*force_display*/); - break; - } case SymbolKind::Func: { QueryFunc &func = db->GetFunc(sym); const QueryFunc::Def *def = func.AnyDef(); if (!def) continue; - - int16_t offset = 0; - - // For functions, the outline will report a location that is using the - // extent since that is better for outline. This tries to convert the - // extent location to the spelling location. - auto try_ensure_spelling = [&](Use use) { - Maybe def = GetDefinitionSpell(db, use); - if (!def || def->range.start.line != use.range.start.line) { - return use; - } - return *def; - }; - - std::vector base_callers = GetUsesForAllBases(db, func); - std::vector derived_callers = GetUsesForAllDerived(db, func); - if (base_callers.empty() && derived_callers.empty()) { - Use loc = try_ensure_spelling(use); - AddCodeLens("call", "calls", &common, - OffsetStartColumn(loc, offset++), func.uses, - true /*force_display*/); - } else { - Use loc = try_ensure_spelling(use); - AddCodeLens("direct call", "direct calls", &common, - OffsetStartColumn(loc, offset++), func.uses, - false /*force_display*/); - if (!base_callers.empty()) - AddCodeLens("base call", "base calls", &common, - OffsetStartColumn(loc, offset++), base_callers, - false /*force_display*/); - if (!derived_callers.empty()) - AddCodeLens("derived call", "derived calls", &common, - OffsetStartColumn(loc, offset++), derived_callers, - false /*force_display*/); - } - - AddCodeLens( - "derived", "derived", &common, OffsetStartColumn(use, offset++), - GetFuncDeclarations(db, func.derived), false /*force_display*/); - - // "Base" - if (def->bases.size() == 1) { - Maybe base_loc = GetDefinitionSpell( - db, SymbolIdx{def->bases[0], SymbolKind::Func}); - if (base_loc) { - std::optional ls_base = - GetLsLocation(db, working_files, *base_loc); - if (ls_base) { - std::optional range = - GetLsRange(common.working_file, sym.range); - if (range) { - TCodeLens code_lens; - code_lens.range = *range; - code_lens.range.start.character += offset++; - code_lens.command = lsCommand(); - code_lens.command->title = "Base"; - code_lens.command->command = "ccls.goto"; - code_lens.command->arguments.uri = ls_base->uri; - code_lens.command->arguments.position = ls_base->range.start; - out.result.push_back(code_lens); - } - } - } - } else { - AddCodeLens("base", "base", &common, OffsetStartColumn(use, 1), - GetTypeDeclarations(db, def->bases), - false /*force_display*/); - } - + std::vector base_uses = GetUsesForAllBases(db, func); + std::vector derived_uses = GetUsesForAllDerived(db, func); + Add("ref", {sym.usr, SymbolKind::Func, "uses"}, use, func.uses.size(), + base_uses.empty()); + if (base_uses.size()) + Add("b.ref", {sym.usr, SymbolKind::Func, "bases uses"}, use, + base_uses.size()); + if (derived_uses.size()) + Add("d.ref", {sym.usr, SymbolKind::Func, "derived uses"}, use, + derived_uses.size()); + if (base_uses.empty()) + Add("base", {sym.usr, SymbolKind::Func, "bases"}, use, + def->bases.size()); + Add("derived", {sym.usr, SymbolKind::Func, "derived"}, use, + func.derived.size()); + break; + } + case SymbolKind::Type: { + QueryType &type = db->GetType(sym); + Add("ref", {sym.usr, SymbolKind::Type, "uses"}, use, type.uses.size(), + true); + Add("derived", {sym.usr, SymbolKind::Type, "derived"}, use, + type.derived.size()); + Add("var", {sym.usr, SymbolKind::Type, "instances"}, use, + type.instances.size()); break; } case SymbolKind::Var: { @@ -218,27 +168,88 @@ struct Handler_TextDocumentCodeLens const QueryVar::Def *def = var.AnyDef(); if (!def || (def->is_local() && !g_config->codeLens.localVariables)) continue; - - bool force_display = true; - // Do not show 0 refs on macro with no uses, as it is most likely - // a header guard. - if (def->kind == lsSymbolKind::Macro) - force_display = false; - - AddCodeLens("ref", "refs", &common, OffsetStartColumn(use, 0), var.uses, - force_display); + Add("ref", {sym.usr, SymbolKind::Var, "uses"}, use, var.uses.size(), + def->kind != lsSymbolKind::Macro); break; } case SymbolKind::File: - case SymbolKind::Invalid: { - assert(false && "unexpected"); - break; - } + case SymbolKind::Invalid: + llvm_unreachable(""); }; } - pipeline::WriteStdout(kMethodType, out); + pipeline::WriteStdout(codeLens, out); } }; REGISTER_MESSAGE_HANDLER(Handler_TextDocumentCodeLens); + +struct In_WorkspaceExecuteCommand : public RequestInMessage { + MethodType GetMethodType() const override { return executeCommand; } + lsCommand params; +}; +MAKE_REFLECT_STRUCT(In_WorkspaceExecuteCommand, id, params); +REGISTER_IN_MESSAGE(In_WorkspaceExecuteCommand); + +struct Handler_WorkspaceExecuteCommand + : BaseMessageHandler { + MethodType GetMethodType() const override { return executeCommand; } + void Run(In_WorkspaceExecuteCommand *request) override { + const auto ¶ms = request->params; + if (params.arguments.empty()) + return; + rapidjson::Document reader; + reader.Parse(params.arguments[0].c_str()); + JsonReader json_reader{&reader}; + if (params.command == ccls_xref) { + Cmd_xref cmd; + Reflect(json_reader, cmd); + Out_xref out; + out.id = request->id; + auto Map = [&](auto &&uses) { + for (auto &use : uses) + if (auto loc = GetLsLocation(db, working_files, use)) + out.result.push_back(std::move(*loc)); + }; + switch (cmd.kind) { + case SymbolKind::Func: { + QueryFunc &func = db->Func(cmd.usr); + if (cmd.field == "bases") { + if (auto *def = func.AnyDef()) + Map(GetFuncDeclarations(db, def->bases)); + } else if (cmd.field == "bases uses") { + Map(GetUsesForAllBases(db, func)); + } else if (cmd.field == "derived") { + Map(GetFuncDeclarations(db, func.derived)); + } else if (cmd.field == "derived uses") { + Map(GetUsesForAllDerived(db, func)); + } else if (cmd.field == "uses") { + Map(func.uses); + } + break; + } + case SymbolKind::Type: { + QueryType &type = db->Type(cmd.usr); + if (cmd.field == "derived") { + Map(GetTypeDeclarations(db, type.derived)); + } else if (cmd.field == "instances") { + Map(GetVarDeclarations(db, type.instances, 7)); + } else if (cmd.field == "uses") { + Map(type.uses); + } + break; + } + case SymbolKind::Var: { + QueryVar &var = db->Var(cmd.usr); + if (cmd.field == "uses") + Map(var.uses); + break; + } + default: + break; + } + pipeline::WriteStdout(executeCommand, out); + } + } +}; +REGISTER_MESSAGE_HANDLER(Handler_WorkspaceExecuteCommand); } // namespace diff --git a/src/messages/textDocument_completion.cc b/src/messages/textDocument_completion.cc index 9582b578..411e4763 100644 --- a/src/messages/textDocument_completion.cc +++ b/src/messages/textDocument_completion.cc @@ -13,19 +13,23 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "fuzzy_match.h" #include "include_complete.h" +#include "log.hh" #include "message_handler.h" #include "pipeline.hh" #include "working_files.h" -using namespace ccls; -#include -using namespace llvm; +#include +#include #include +using namespace ccls; +using namespace clang; +using namespace llvm; + namespace { MethodType kMethodType = "textDocument/completion"; @@ -175,10 +179,6 @@ void FilterAndSortCompletionResponse( const std::string &complete_text, bool has_open_paren) { if (!g_config->completion.filterAndSort) return; - - static Timer timer("FilterAndSortCompletionResponse", ""); - TimeRegion region(timer); - auto &items = complete_response->result.items; auto finalize = [&]() { @@ -261,24 +261,250 @@ bool IsOpenParenOrAngle(const std::vector &lines, return false; } -struct Handler_TextDocumentCompletion : MessageHandler { +unsigned GetCompletionPriority(const CodeCompletionString &CCS, + CXCursorKind result_kind, + const std::optional &typedText) { + unsigned priority = CCS.getPriority(); + if (CCS.getAvailability() != CXAvailability_Available || + result_kind == CXCursor_Destructor || + result_kind == CXCursor_ConversionFunction || + (result_kind == CXCursor_CXXMethod && typedText && + StartsWith(*typedText, "operator"))) + priority *= 100; + return priority; +} + +lsCompletionItemKind GetCompletionKind(CXCursorKind cursor_kind) { + switch (cursor_kind) { + case CXCursor_UnexposedDecl: + return lsCompletionItemKind::Text; + + case CXCursor_StructDecl: + case CXCursor_UnionDecl: + return lsCompletionItemKind::Struct; + case CXCursor_ClassDecl: + return lsCompletionItemKind::Class; + case CXCursor_EnumDecl: + return lsCompletionItemKind::Enum; + case CXCursor_FieldDecl: + return lsCompletionItemKind::Field; + case CXCursor_EnumConstantDecl: + return lsCompletionItemKind::EnumMember; + case CXCursor_FunctionDecl: + return lsCompletionItemKind::Function; + case CXCursor_VarDecl: + case CXCursor_ParmDecl: + return lsCompletionItemKind::Variable; + case CXCursor_ObjCInterfaceDecl: + return lsCompletionItemKind::Interface; + + case CXCursor_ObjCInstanceMethodDecl: + case CXCursor_CXXMethod: + case CXCursor_ObjCClassMethodDecl: + return lsCompletionItemKind::Method; + + case CXCursor_FunctionTemplate: + return lsCompletionItemKind::Function; + + case CXCursor_Constructor: + case CXCursor_Destructor: + case CXCursor_ConversionFunction: + return lsCompletionItemKind::Constructor; + + case CXCursor_ObjCIvarDecl: + return lsCompletionItemKind::Variable; + + case CXCursor_ClassTemplate: + case CXCursor_ClassTemplatePartialSpecialization: + case CXCursor_UsingDeclaration: + case CXCursor_TypedefDecl: + case CXCursor_TypeAliasDecl: + case CXCursor_TypeAliasTemplateDecl: + case CXCursor_ObjCCategoryDecl: + case CXCursor_ObjCProtocolDecl: + case CXCursor_ObjCImplementationDecl: + case CXCursor_ObjCCategoryImplDecl: + return lsCompletionItemKind::Class; + + case CXCursor_ObjCPropertyDecl: + return lsCompletionItemKind::Property; + + case CXCursor_MacroInstantiation: + case CXCursor_MacroDefinition: + return lsCompletionItemKind::Interface; + + case CXCursor_Namespace: + case CXCursor_NamespaceAlias: + case CXCursor_NamespaceRef: + return lsCompletionItemKind::Module; + + case CXCursor_MemberRef: + case CXCursor_TypeRef: + case CXCursor_ObjCSuperClassRef: + case CXCursor_ObjCProtocolRef: + case CXCursor_ObjCClassRef: + return lsCompletionItemKind::Reference; + + // return lsCompletionItemKind::Unit; + // return lsCompletionItemKind::Value; + // return lsCompletionItemKind::Keyword; + // return lsCompletionItemKind::Snippet; + // return lsCompletionItemKind::Color; + // return lsCompletionItemKind::File; + + case CXCursor_NotImplemented: + case CXCursor_OverloadCandidate: + return lsCompletionItemKind::Text; + + case CXCursor_TemplateTypeParameter: + case CXCursor_TemplateTemplateParameter: + return lsCompletionItemKind::TypeParameter; + + default: + LOG_S(WARNING) << "Unhandled completion kind " << cursor_kind; + return lsCompletionItemKind::Text; + } +} + +void BuildItem(std::vector &out, + const CodeCompletionString &CCS) { + assert(!out.empty()); + auto first = out.size() - 1; + + std::string result_type; + + for (const auto &Chunk : CCS) { + CodeCompletionString::ChunkKind Kind = Chunk.Kind; + std::string text; + switch (Kind) { + case CodeCompletionString::CK_TypedText: + text = Chunk.Text; + for (auto i = first; i < out.size(); i++) + if (Kind == CodeCompletionString::CK_TypedText && !out[i].filterText) + out[i].filterText = text; + break; + case CodeCompletionString::CK_Placeholder: + text = Chunk.Text; + for (auto i = first; i < out.size(); i++) + out[i].parameters_.push_back(text); + break; + case CodeCompletionString::CK_Informative: + if (StringRef(Chunk.Text).endswith("::")) + continue; + text = Chunk.Text; + break; + case CodeCompletionString::CK_ResultType: + result_type = Chunk.Text; + continue; + case CodeCompletionString::CK_CurrentParameter: + // This should never be present while collecting completion items. + llvm_unreachable("unexpected CK_CurrentParameter"); + continue; + case CodeCompletionString::CK_Optional: { + // Duplicate last element, the recursive call will complete it. + if (g_config->completion.duplicateOptional) { + out.push_back(out.back()); + BuildItem(out, *Chunk.Optional); + } + continue; + } + default: + text = Chunk.Text; + break; + } + + for (auto i = first; i < out.size(); ++i) { + out[i].label += text; + if (!g_config->client.snippetSupport && !out[i].parameters_.empty()) + continue; + + if (Kind == CodeCompletionString::CK_Placeholder) { + out[i].insertText += + "${" + std::to_string(out[i].parameters_.size()) + ":" + text + "}"; + out[i].insertTextFormat = lsInsertTextFormat::Snippet; + } else if (Kind != CodeCompletionString::CK_Informative) { + out[i].insertText += text; + } + } + } + + if (result_type.size()) + for (auto i = first; i < out.size(); ++i) { + // ' : ' for variables, + // ' -> ' (trailing return type-like) for functions + out[i].label += (out[i].label == out[i].filterText ? " : " : " -> "); + out[i].label += result_type; + } +} + +class CompletionConsumer : public CodeCompleteConsumer { + std::shared_ptr Alloc; + CodeCompletionTUInfo CCTUInfo; + +public: + bool from_cache; + std::vector ls_items; + + CompletionConsumer(const CodeCompleteOptions &Opts, bool from_cache) + : CodeCompleteConsumer(Opts, false), + Alloc(std::make_shared()), + CCTUInfo(Alloc), from_cache(from_cache) {} + + void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, + CodeCompletionResult *Results, + unsigned NumResults) override { + ls_items.reserve(NumResults); + for (unsigned i = 0; i != NumResults; i++) { + auto &R = Results[i]; + if (R.Availability == CXAvailability_NotAccessible || + R.Availability == CXAvailability_NotAvailable) + continue; + CodeCompletionString *CCS = R.CreateCodeCompletionString( + S, Context, getAllocator(), getCodeCompletionTUInfo(), + includeBriefComments()); + lsCompletionItem ls_item; + ls_item.kind = GetCompletionKind(R.CursorKind); + if (const char *brief = CCS->getBriefComment()) + ls_item.documentation = brief; + ls_item.detail = CCS->getParentContextName().str(); + + size_t first_idx = ls_items.size(); + ls_items.push_back(ls_item); + BuildItem(ls_items, *CCS); + + for (size_t j = first_idx; j < ls_items.size(); j++) { + if (g_config->client.snippetSupport && + ls_items[j].insertTextFormat == lsInsertTextFormat::Snippet) + ls_items[j].insertText += "$0"; + ls_items[j].priority_ = GetCompletionPriority( + *CCS, Results[i].CursorKind, ls_items[j].filterText); + if (!g_config->completion.detailedLabel) { + ls_items[j].detail = ls_items[j].label; + ls_items[j].label = ls_items[j].filterText.value_or(""); + } + } + } + } + + CodeCompletionAllocator &getAllocator() override { return *Alloc; } + CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } +}; + +struct Handler_TextDocumentCompletion + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - void Run(std::unique_ptr message) override { - auto request = std::shared_ptr( - static_cast(message.release())); - auto ¶ms = request->params; + void Run(In_TextDocumentComplete *request) override { + static CompleteConsumerCache> cache; - auto write_empty_result = [request]() { - Out_TextDocumentComplete out; - out.id = request->id; - pipeline::WriteStdout(kMethodType, out); - }; + auto ¶ms = request->params; + Out_TextDocumentComplete out; + out.id = request->id; std::string path = params.textDocument.uri.GetPath(); WorkingFile *file = working_files->GetFileByFilename(path); if (!file) { - write_empty_result(); + pipeline::WriteStdout(kMethodType, out); return; } @@ -323,19 +549,15 @@ struct Handler_TextDocumentCompletion : MessageHandler { } if (did_fail_check) { - write_empty_result(); + pipeline::WriteStdout(kMethodType, out); return; } } - bool is_global_completion = false; - std::string existing_completion; + std::string completion_text; lsPosition end_pos = params.position; - if (file) { - params.position = file->FindStableCompletionSource( - request->params.position, &is_global_completion, &existing_completion, - &end_pos); - } + params.position = file->FindStableCompletionSource( + request->params.position, &completion_text, &end_pos); ParseIncludeLineResult result = ParseIncludeLine(buffer_line); bool has_open_paren = IsOpenParenOrAngle(file->buffer_lines, end_pos); @@ -380,69 +602,45 @@ struct Handler_TextDocumentCompletion : MessageHandler { pipeline::WriteStdout(kMethodType, out); } else { - ClangCompleteManager::OnComplete callback = std::bind( - [this, request, params, is_global_completion, existing_completion, - has_open_paren](const std::vector &results, - bool is_cached_result) { + CompletionManager::OnComplete callback = + [completion_text, has_open_paren, id = request->id, + params = request->params](CodeCompleteConsumer *OptConsumer) { + if (!OptConsumer) + return; + auto *Consumer = static_cast(OptConsumer); Out_TextDocumentComplete out; - out.id = request->id; - out.result.items = results; + out.id = id; + out.result.items = Consumer->ls_items; - // Emit completion results. - FilterAndSortCompletionResponse(&out, existing_completion, + FilterAndSortCompletionResponse(&out, completion_text, has_open_paren); pipeline::WriteStdout(kMethodType, out); - - // Cache completion results. - if (!is_cached_result) { + if (!Consumer->from_cache) { std::string path = params.textDocument.uri.GetPath(); - if (is_global_completion) { - global_code_complete_cache->WithLock([&]() { - global_code_complete_cache->cached_path_ = path; - global_code_complete_cache->cached_results_ = results; - }); - } else { - non_global_code_complete_cache->WithLock([&]() { - non_global_code_complete_cache->cached_path_ = path; - non_global_code_complete_cache->cached_completion_position_ = - params.position; - non_global_code_complete_cache->cached_results_ = results; - }); - } - } - }, - std::placeholders::_1, std::placeholders::_2); - - bool is_cache_match = false; - global_code_complete_cache->WithLock([&]() { - is_cache_match = is_global_completion && - global_code_complete_cache->cached_path_ == path && - !global_code_complete_cache->cached_results_.empty(); - }); - if (is_cache_match) { - ClangCompleteManager::OnComplete freshen_global = - [this](std::vector results, - bool is_cached_result) { - assert(!is_cached_result); - - // note: path is updated in the normal completion handler. - global_code_complete_cache->WithLock([&]() { - global_code_complete_cache->cached_results_ = results; + cache.WithLock([&]() { + cache.path = path; + cache.position = params.position; + cache.result = Consumer->ls_items; }); - }; + } + }; - global_code_complete_cache->WithLock([&]() { - callback(global_code_complete_cache->cached_results_, - true /*is_cached_result*/); - }); - clang_complete->CodeComplete(request->id, params, freshen_global); - } else if (non_global_code_complete_cache->IsCacheValid(params)) { - non_global_code_complete_cache->WithLock([&]() { - callback(non_global_code_complete_cache->cached_results_, - true /*is_cached_result*/); - }); + clang::CodeCompleteOptions CCOpts; + CCOpts.IncludeBriefComments = true; +#if LLVM_VERSION_MAJOR >= 7 + CCOpts.IncludeFixIts = true; +#endif + CCOpts.IncludeMacros = true; + if (cache.IsCacheValid(params)) { + CompletionConsumer Consumer(CCOpts, true); + cache.WithLock([&]() { Consumer.ls_items = cache.result; }); + callback(&Consumer); } else { - clang_complete->CodeComplete(request->id, params, callback); + clang_complete->completion_request_.PushBack( + std::make_unique( + request->id, params.textDocument, params.position, + std::make_unique(CCOpts, false), CCOpts, + callback)); } } } diff --git a/src/messages/textDocument_definition.cc b/src/messages/textDocument_definition.cc index 7794bfd1..2718abd7 100644 --- a/src/messages/textDocument_definition.cc +++ b/src/messages/textDocument_definition.cc @@ -16,11 +16,12 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; -#include #include #include +#include + +using namespace ccls; namespace { MethodType kMethodType = "textDocument/definition"; @@ -43,7 +44,7 @@ std::vector GetNonDefDeclarationTargets(DB *db, SymbolRef sym) { switch (sym.kind) { case SymbolKind::Var: { std::vector ret = GetNonDefDeclarations(db, sym); - // If there is no declaration, jump the its type. + // If there is no declaration, jump to its type. if (ret.empty()) { for (auto &def : db->GetVar(sym).def) if (def.type) { @@ -76,64 +77,61 @@ struct Handler_TextDocumentDefinition out.id = request->id; Maybe on_def; - bool has_symbol = false; WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); lsPosition &ls_pos = params.position; - for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos)) { - // Found symbol. Return definition. - has_symbol = true; - + for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, ls_pos, true)) { // Special cases which are handled: // - symbol has declaration but no definition (ie, pure virtual) - // - start at spelling but end at extent for better mouse tooltip // - goto declaration while in definition of recursive type std::vector uses; EachEntityDef(db, sym, [&](const auto &def) { - if (def.spell && def.extent) { + if (def.spell) { Use spell = *def.spell; - // If on a definition, clear |uses| to find declarations below. if (spell.file_id == file_id && spell.range.Contains(ls_pos.line, ls_pos.character)) { on_def = spell; uses.clear(); return false; } - // We use spelling start and extent end because this causes vscode - // to highlight the entire definition when previewing / hoving with - // the mouse. - spell.range.end = def.extent->range.end; uses.push_back(spell); } return true; }); + // |uses| is empty if on a declaration/definition, otherwise it includes + // all declarations/definitions. if (uses.empty()) { - // The symbol has no definition or the cursor is on a definition. - uses = GetNonDefDeclarationTargets(db, sym); + for (Use use : GetNonDefDeclarationTargets(db, sym)) + if (!(use.file_id == file_id && + use.range.Contains(ls_pos.line, ls_pos.character))) + uses.push_back(use); // There is no declaration but the cursor is on a definition. if (uses.empty() && on_def) uses.push_back(*on_def); } auto locs = GetLsLocationExs(db, working_files, uses); out.result.insert(out.result.end(), locs.begin(), locs.end()); - if (!out.result.empty()) - break; } - // No symbols - check for includes. - if (out.result.empty()) { + if (out.result.size()) { + std::sort(out.result.begin(), out.result.end()); + out.result.erase(std::unique(out.result.begin(), out.result.end()), + out.result.end()); + } else { + Maybe range; + // Check #include for (const IndexInclude &include : file->def->includes) { if (include.line == ls_pos.line) { lsLocationEx result; result.uri = lsDocumentUri::FromPath(include.resolved_path); out.result.push_back(result); - has_symbol = true; + range = {{0, 0}, {0, 0}}; break; } } // Find the best match of the identifier at point. - if (!has_symbol) { + if (!range) { lsPosition position = request->params.position; const std::string &buffer = wfile->buffer_content; std::string_view query = LexIdentifierAroundPos(position, buffer); diff --git a/src/messages/textDocument_did.cc b/src/messages/textDocument_did.cc new file mode 100644 index 00000000..30bf2acd --- /dev/null +++ b/src/messages/textDocument_did.cc @@ -0,0 +1,167 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "clang_complete.hh" +#include "include_complete.h" +#include "message_handler.h" +#include "pipeline.hh" +#include "project.h" +#include "working_files.h" +using namespace ccls; + +namespace { +MethodType didChange = "textDocument/didChange"; +MethodType didClose = "textDocument/didClose"; +MethodType didOpen = "textDocument/didOpen"; +MethodType didSave = "textDocument/didSave"; + +struct In_TextDocumentDidChange : public NotificationInMessage { + MethodType GetMethodType() const override { return didChange; } + lsTextDocumentDidChangeParams params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidChange, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidChange); + +struct Handler_TextDocumentDidChange + : BaseMessageHandler { + MethodType GetMethodType() const override { return didChange; } + + void Run(In_TextDocumentDidChange *request) override { + const auto ¶ms = request->params; + std::string path = params.textDocument.uri.GetPath(); + working_files->OnChange(params); + if (g_config->index.onChange) + pipeline::Index(path, {}, IndexMode::OnChange); + clang_complete->NotifyView(path); + if (g_config->diagnostics.onChange >= 0) + clang_complete->DiagnosticsUpdate(path, g_config->diagnostics.onChange); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidChange); + +struct In_TextDocumentDidClose : public NotificationInMessage { + MethodType GetMethodType() const override { return didClose; } + struct Params { + lsTextDocumentIdentifier textDocument; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidClose::Params, textDocument); +MAKE_REFLECT_STRUCT(In_TextDocumentDidClose, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidClose); + +struct Handler_TextDocumentDidClose + : BaseMessageHandler { + MethodType GetMethodType() const override { return didClose; } + + void Run(In_TextDocumentDidClose *request) override { + std::string path = request->params.textDocument.uri.GetPath(); + + // Clear any diagnostics for the file. + Out_TextDocumentPublishDiagnostics out; + out.params.uri = request->params.textDocument.uri; + pipeline::WriteStdout(didClose, out); + + // Remove internal state. + working_files->OnClose(request->params.textDocument); + clang_complete->OnClose(path); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidClose); + +struct In_TextDocumentDidOpen : public NotificationInMessage { + MethodType GetMethodType() const override { return didOpen; } + + struct Params { + lsTextDocumentItem textDocument; + + // ccls extension + // If specified (e.g. ["clang++", "-DM", "a.cc"]), it overrides the project + // entry (e.g. loaded from compile_commands.json or .ccls). + std::vector args; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen::Params, textDocument, args); +MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidOpen); + +struct Handler_TextDocumentDidOpen + : BaseMessageHandler { + MethodType GetMethodType() const override { return didOpen; } + + void Run(In_TextDocumentDidOpen *request) override { + // NOTE: This function blocks code lens. If it starts taking a long time + // we will need to find a way to unblock the code lens request. + const auto ¶ms = request->params; + const std::string &path = params.textDocument.uri.GetPath(); + + WorkingFile *working_file = working_files->OnOpen(params.textDocument); + if (std::optional cached_file_contents = + pipeline::LoadIndexedContent(path)) + working_file->SetIndexContent(*cached_file_contents); + + QueryFile *file = nullptr; + FindFileOrFail(db, project, std::nullopt, path, &file); + if (file && file->def) { + EmitSkippedRanges(working_file, file->def->skipped_ranges); + EmitSemanticHighlighting(db, working_file, file); + } + + include_complete->AddFile(working_file->filename); + std::vector args; + for (const std::string &arg : params.args) + args.push_back(Intern(arg)); + if (args.size()) + project->SetArgsForFile(args, path); + + // Submit new index request if it is not a header file or there is no + // pending index request. + if (SourceFileLanguage(path) != LanguageId::Unknown || + !pipeline::pending_index_requests) + pipeline::Index(path, args, IndexMode::Normal); + + clang_complete->NotifyView(path); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen); + +struct In_TextDocumentDidSave : public NotificationInMessage { + MethodType GetMethodType() const override { return didSave; } + + struct Params { + // The document that was saved. + lsTextDocumentIdentifier textDocument; + + // Optional the content when saved. Depends on the includeText value + // when the save notifcation was requested. + // std::string text; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentDidSave::Params, textDocument); +MAKE_REFLECT_STRUCT(In_TextDocumentDidSave, params); +REGISTER_IN_MESSAGE(In_TextDocumentDidSave); + +struct Handler_TextDocumentDidSave + : BaseMessageHandler { + MethodType GetMethodType() const override { return didSave; } + + void Run(In_TextDocumentDidSave *request) override { + const auto ¶ms = request->params; + const std::string &path = params.textDocument.uri.GetPath(); + pipeline::Index(path, {}, IndexMode::Normal); + clang_complete->NotifySave(path); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave); +} // namespace diff --git a/src/messages/textDocument_didChange.cc b/src/messages/textDocument_didChange.cc deleted file mode 100644 index a0690a2c..00000000 --- a/src/messages/textDocument_didChange.cc +++ /dev/null @@ -1,51 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.h" -#include "message_handler.h" -#include "pipeline.hh" -#include "project.h" -#include "working_files.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didChange"; - -struct In_TextDocumentDidChange : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsTextDocumentDidChangeParams params; -}; - -MAKE_REFLECT_STRUCT(In_TextDocumentDidChange, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidChange); - -struct Handler_TextDocumentDidChange - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidChange *request) override { - std::string path = request->params.textDocument.uri.GetPath(); - working_files->OnChange(request->params); - if (g_config->index.onDidChange) { - Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, entry.args, true); - } - clang_complete->NotifyEdit(path); - clang_complete->DiagnosticsUpdate( - request->params.textDocument.AsTextDocumentIdentifier()); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidChange); -} // namespace diff --git a/src/messages/textDocument_didClose.cc b/src/messages/textDocument_didClose.cc deleted file mode 100644 index 8187ee7d..00000000 --- a/src/messages/textDocument_didClose.cc +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.h" -#include "message_handler.h" -#include "pipeline.hh" -#include "working_files.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didClose"; - -struct In_TextDocumentDidClose : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - struct Params { - lsTextDocumentIdentifier textDocument; - }; - Params params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentDidClose::Params, textDocument); -MAKE_REFLECT_STRUCT(In_TextDocumentDidClose, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidClose); - -struct Handler_TextDocumentDidClose - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidClose *request) override { - std::string path = request->params.textDocument.uri.GetPath(); - - // Clear any diagnostics for the file. - Out_TextDocumentPublishDiagnostics out; - out.params.uri = request->params.textDocument.uri; - pipeline::WriteStdout(kMethodType, out); - - // Remove internal state. - working_files->OnClose(request->params.textDocument); - clang_complete->NotifyClose(path); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidClose); -} // namespace diff --git a/src/messages/textDocument_didOpen.cc b/src/messages/textDocument_didOpen.cc deleted file mode 100644 index c9d63e8e..00000000 --- a/src/messages/textDocument_didOpen.cc +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.h" -#include "include_complete.h" -#include "message_handler.h" -#include "pipeline.hh" -#include "project.h" -#include "working_files.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didOpen"; - -// Open, view, change, close file -struct In_TextDocumentDidOpen : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - - struct Params { - lsTextDocumentItem textDocument; - - // ccls extension - // If specified (e.g. ["clang++", "-DM", "a.cc"]), it overrides the project - // entry (e.g. loaded from compile_commands.json or .ccls). - std::vector args; - }; - Params params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen::Params, textDocument, args); -MAKE_REFLECT_STRUCT(In_TextDocumentDidOpen, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidOpen); - -struct Handler_TextDocumentDidOpen - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidOpen *request) override { - // NOTE: This function blocks code lens. If it starts taking a long time - // we will need to find a way to unblock the code lens request. - const auto ¶ms = request->params; - std::string path = params.textDocument.uri.GetPath(); - - WorkingFile *working_file = working_files->OnOpen(params.textDocument); - if (std::optional cached_file_contents = - pipeline::LoadCachedFileContents(path)) - working_file->SetIndexContent(*cached_file_contents); - - QueryFile *file = nullptr; - FindFileOrFail(db, project, std::nullopt, path, &file); - if (file && file->def) { - EmitSkippedRanges(working_file, file->def->skipped_ranges); - EmitSemanticHighlighting(db, semantic_cache, working_file, file); - } - - include_complete->AddFile(working_file->filename); - if (params.args.size()) - project->SetFlagsForFile(params.args, path); - - // Submit new index request if it is not a header file. - if (SourceFileLanguage(path) != LanguageId::Unknown) { - Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, - params.args.size() ? params.args : entry.args, true); - - clang_complete->FlushSession(entry.filename); - } - - clang_complete->NotifyView(path); - if (g_config->diagnostics.onParse) - clang_complete->DiagnosticsUpdate({params.textDocument.uri}); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidOpen); -} // namespace diff --git a/src/messages/textDocument_didSave.cc b/src/messages/textDocument_didSave.cc deleted file mode 100644 index 17bb53ff..00000000 --- a/src/messages/textDocument_didSave.cc +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "clang_complete.h" -#include "message_handler.h" -#include "pipeline.hh" -#include "project.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "textDocument/didSave"; - -struct In_TextDocumentDidSave : public NotificationInMessage { - MethodType GetMethodType() const override { return kMethodType; } - - struct Params { - // The document that was saved. - lsTextDocumentIdentifier textDocument; - - // Optional the content when saved. Depends on the includeText value - // when the save notifcation was requested. - // std::string text; - }; - Params params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentDidSave::Params, textDocument); -MAKE_REFLECT_STRUCT(In_TextDocumentDidSave, params); -REGISTER_IN_MESSAGE(In_TextDocumentDidSave); - -struct Handler_TextDocumentDidSave - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - - void Run(In_TextDocumentDidSave *request) override { - const auto ¶ms = request->params; - std::string path = params.textDocument.uri.GetPath(); - - // Send out an index request, and copy the current buffer state so we - // can update the cached index contents when the index is done. - // - // We also do not index if there is already an index request or if - // the client requested indexing on didChange instead. - // - // TODO: Cancel outgoing index request. Might be tricky to make - // efficient since we have to cancel. - // - we could have an |atomic active_cancellations| variable - // that all of the indexers check before accepting an index. if - // zero we don't slow down fast-path. if non-zero we acquire - // mutex and check to see if we should skip the current request. - // if so, ignore that index response. - // TODO: send as priority request - if (!g_config->index.onDidChange) { - Project::Entry entry = project->FindCompilationEntryForFile(path); - pipeline::Index(entry.filename, entry.args, true); - } - - clang_complete->NotifySave(path); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_TextDocumentDidSave); -} // namespace diff --git a/src/messages/textDocument_documentHighlight.cc b/src/messages/textDocument_documentHighlight.cc index 871f617b..e3d6e35d 100644 --- a/src/messages/textDocument_documentHighlight.cc +++ b/src/messages/textDocument_documentHighlight.cc @@ -17,11 +17,28 @@ limitations under the License. #include "pipeline.hh" #include "query_utils.h" #include "symbol.h" + +#include using namespace ccls; namespace { MethodType kMethodType = "textDocument/documentHighlight"; +struct lsDocumentHighlight { + enum Kind { Text = 1, Read = 2, Write = 3 }; + + lsRange range; + int kind = 1; + + // ccls extension + Role role = Role::None; + + bool operator<(const lsDocumentHighlight &o) const { + return !(range == o.range) ? range < o.range : kind < o.kind; + } +}; +MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind, role); + struct In_TextDocumentDocumentHighlight : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } lsTextDocumentPositionParams params; @@ -44,39 +61,41 @@ struct Handler_TextDocumentDocumentHighlight QueryFile *file; if (!FindFileOrFail(db, project, request->id, request->params.textDocument.uri.GetPath(), &file, - &file_id)) { + &file_id)) return; - } - WorkingFile *working_file = working_files->GetFileByFilename(file->def->path); Out_TextDocumentDocumentHighlight out; out.id = request->id; - for (SymbolRef sym : - FindSymbolsAtLocation(working_file, file, request->params.position)) { - // Found symbol. Return references to highlight. - EachOccurrence(db, sym, true, [&](Use use) { - if (use.file_id != file_id) - return; - if (std::optional ls_loc = - GetLsLocation(db, working_files, use)) { - lsDocumentHighlight highlight; - highlight.range = ls_loc->range; - if (use.role & Role::Write) - highlight.kind = lsDocumentHighlightKind::Write; - else if (use.role & Role::Read) - highlight.kind = lsDocumentHighlightKind::Read; - else - highlight.kind = lsDocumentHighlightKind::Text; - highlight.role = use.role; - out.result.push_back(highlight); - } - }); - break; + std::vector syms = FindSymbolsAtLocation( + working_file, file, request->params.position, true); + for (auto [sym, refcnt] : file->symbol2refcnt) { + if (refcnt <= 0) + continue; + Usr usr = sym.usr; + SymbolKind kind = sym.kind; + if (std::none_of(syms.begin(), syms.end(), [&](auto &sym1) { + return usr == sym1.usr && kind == sym1.kind; + })) + continue; + if (auto ls_loc = + GetLsLocation(db, working_files, + Use{{sym.range, usr, kind, sym.role}, file_id})) { + lsDocumentHighlight highlight; + highlight.range = ls_loc->range; + if (sym.role & Role::Write) + highlight.kind = lsDocumentHighlight::Write; + else if (sym.role & Role::Read) + highlight.kind = lsDocumentHighlight::Read; + else + highlight.kind = lsDocumentHighlight::Text; + highlight.role = sym.role; + out.result.push_back(highlight); + } } - + std::sort(out.result.begin(), out.result.end()); pipeline::WriteStdout(kMethodType, out); } }; diff --git a/src/messages/textDocument_documentSymbol.cc b/src/messages/textDocument_documentSymbol.cc index 2704d914..bda4a270 100644 --- a/src/messages/textDocument_documentSymbol.cc +++ b/src/messages/textDocument_documentSymbol.cc @@ -19,20 +19,24 @@ limitations under the License. using namespace ccls; using namespace clang; +MAKE_HASHABLE(SymbolIdx, t.usr, t.kind); + namespace { MethodType kMethodType = "textDocument/documentSymbol"; -struct lsDocumentSymbolParams { - lsTextDocumentIdentifier textDocument; - int startLine = -1; - int endLine = -1; -}; -MAKE_REFLECT_STRUCT(lsDocumentSymbolParams, textDocument, startLine, endLine); - struct In_TextDocumentDocumentSymbol : public RequestInMessage { MethodType GetMethodType() const override { return kMethodType; } - lsDocumentSymbolParams params; + struct Params { + lsTextDocumentIdentifier textDocument; + // false: outline; true: all symbols + bool all = false; + // If >= 0, return Range[] instead of SymbolInformation[] to reduce output. + int startLine = -1; + int endLine = -1; + } params; }; +MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol::Params, textDocument, all, + startLine, endLine); MAKE_REFLECT_STRUCT(In_TextDocumentDocumentSymbol, id, params); REGISTER_IN_MESSAGE(In_TextDocumentDocumentSymbol); @@ -50,6 +54,36 @@ struct Out_TextDocumentDocumentSymbol }; MAKE_REFLECT_STRUCT(Out_TextDocumentDocumentSymbol, jsonrpc, id, result); +struct lsDocumentSymbol { + std::string name; + std::string detail; + lsSymbolKind kind; + lsRange range; + lsRange selectionRange; + std::vector> children; +}; +void Reflect(Writer &vis, std::unique_ptr &v); +MAKE_REFLECT_STRUCT(lsDocumentSymbol, name, detail, kind, range, selectionRange, + children); +void Reflect(Writer &vis, std::unique_ptr &v) { + Reflect(vis, *v); +} + +struct Out_HierarchicalDocumentSymbol + : public lsOutMessage { + lsRequestId id; + std::vector> result; +}; +MAKE_REFLECT_STRUCT(Out_HierarchicalDocumentSymbol, jsonrpc, id, result); + +bool IgnoreType(const QueryType::Def *def) { + return !def || def->kind == lsSymbolKind::TypeParameter; +} + +bool IgnoreVar(const QueryVar::Def *def) { + return !def || def->is_local(); +} + struct Handler_TextDocumentDocumentSymbol : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } @@ -61,32 +95,124 @@ struct Handler_TextDocumentDocumentSymbol if (!FindFileOrFail(db, project, request->id, params.textDocument.uri.GetPath(), &file, &file_id)) return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; + const auto &symbol2refcnt = + params.all ? file->symbol2refcnt : file->outline2refcnt; if (params.startLine >= 0) { Out_SimpleDocumentSymbol out; out.id = request->id; - for (SymbolRef sym : file->def->all_symbols) - if (std::optional location = GetLsLocation( - db, working_files, - Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) { - if (params.startLine <= sym.range.start.line && - sym.range.start.line <= params.endLine) - out.result.push_back(location->range); - } + for (auto [sym, refcnt] : symbol2refcnt) + if (refcnt > 0 && params.startLine <= sym.range.start.line && + sym.range.start.line <= params.endLine) + if (auto ls_loc = GetLsLocation( + db, working_files, + Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) + out.result.push_back(ls_loc->range); std::sort(out.result.begin(), out.result.end()); pipeline::WriteStdout(kMethodType, out); + } else if (g_config->client.hierarchicalDocumentSymbolSupport) { + std::unordered_map< + SymbolIdx, std::pair>> + sym2ds; + for (auto [sym, refcnt] : symbol2refcnt) { + if (refcnt <= 0) + continue; + auto r = sym2ds.try_emplace(SymbolIdx{sym.usr, sym.kind}); + if (!r.second) + continue; + auto &kv = r.first->second; + kv.second = std::make_unique(); + lsDocumentSymbol &ds = *kv.second; + WithEntity(db, sym, [&](const auto &entity) { + auto *def = entity.AnyDef(); + if (!def) + return; + ds.name = def->Name(false); + ds.detail = def->Name(true); + for (auto &def : entity.def) + if (def.file_id == file_id) { + if (!def.spell || !def.extent) + break; + ds.kind = def.kind; + if (auto ls_range = GetLsRange(wfile, def.extent->range)) + ds.range = *ls_range; + else + break; + if (auto ls_range = GetLsRange(wfile, def.spell->range)) + ds.selectionRange = *ls_range; + else + break; + kv.first = static_cast(&def); + } + }); + if (kv.first && ((sym.kind == SymbolKind::Type && + IgnoreType((const QueryType::Def *)kv.first)) || + (sym.kind == SymbolKind::Var && + IgnoreVar((const QueryVar::Def *)kv.first)))) + kv.first = nullptr; + if (!kv.first) { + kv.second.reset(); + continue; + } + } + for (auto &[sym, def_ds] : sym2ds) { + if (!def_ds.second) + continue; + lsDocumentSymbol &ds = *def_ds.second; + switch (sym.kind) { + case SymbolKind::Func: { + auto &def = *static_cast(def_ds.first); + for (Usr usr1 : def.vars) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + break; + } + case SymbolKind::Type: { + auto &def = *static_cast(def_ds.first); + for (Usr usr1 : def.funcs) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Func}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + for (Usr usr1 : def.types) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Type}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + for (auto [usr1, _] : def.vars) { + auto it = sym2ds.find(SymbolIdx{usr1, SymbolKind::Var}); + if (it != sym2ds.end() && it->second.second) + ds.children.push_back(std::move(it->second.second)); + } + break; + } + default: + break; + } + } + Out_HierarchicalDocumentSymbol out; + out.id = request->id; + for (auto &[sym, def_ds] : sym2ds) + if (def_ds.second) + out.result.push_back(std::move(def_ds.second)); + pipeline::WriteStdout(kMethodType, out); } else { Out_TextDocumentDocumentSymbol out; out.id = request->id; - for (SymbolRef sym : file->def->outline) + for (auto [sym, refcnt] : symbol2refcnt) { + if (refcnt <= 0) continue; if (std::optional info = - GetSymbolInfo(db, working_files, sym, false)) { - if (sym.kind == SymbolKind::Var) { - QueryVar &var = db->GetVar(sym); - auto *def = var.AnyDef(); - if (!def || !def->spell || def->is_local()) - continue; - } + GetSymbolInfo(db, sym, false)) { + if ((sym.kind == SymbolKind::Type && + IgnoreType(db->GetType(sym).AnyDef())) || + (sym.kind == SymbolKind::Var && + IgnoreVar(db->GetVar(sym).AnyDef()))) + continue; if (std::optional location = GetLsLocation( db, working_files, Use{{sym.range, sym.usr, sym.kind, sym.role}, file_id})) { @@ -94,6 +220,7 @@ struct Handler_TextDocumentDocumentSymbol out.result.push_back(*info); } } + } pipeline::WriteStdout(kMethodType, out); } } diff --git a/src/messages/textDocument_formatting.cc b/src/messages/textDocument_formatting.cc new file mode 100644 index 00000000..1676a9b5 --- /dev/null +++ b/src/messages/textDocument_formatting.cc @@ -0,0 +1,204 @@ +/* Copyright 2017-2018 ccls Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "message_handler.h" +#include "pipeline.hh" +#include "working_files.h" + +#include +#include + +using namespace ccls; +using namespace clang; + +namespace { +const MethodType formatting = "textDocument/formatting", + onTypeFormatting = "textDocument/onTypeFormatting", + rangeFormatting = "textDocument/rangeFormatting"; + +struct lsFormattingOptions { + // Size of a tab in spaces. + int tabSize; + // Prefer spaces over tabs. + bool insertSpaces; +}; +MAKE_REFLECT_STRUCT(lsFormattingOptions, tabSize, insertSpaces); + +struct Out_TextDocumentFormatting + : public lsOutMessage { + lsRequestId id; + std::vector result; +}; +MAKE_REFLECT_STRUCT(Out_TextDocumentFormatting, jsonrpc, id, result); + +llvm::Expected +FormatCode(std::string_view code, std::string_view file, tooling::Range Range) { + StringRef Code(code.data(), code.size()), File(file.data(), file.size()); + auto Style = format::getStyle("file", File, "LLVM", Code, nullptr); + if (!Style) + return Style.takeError(); + tooling::Replacements IncludeReplaces = + format::sortIncludes(*Style, Code, {Range}, File); + auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces); + if (!Changed) + return Changed.takeError(); + return IncludeReplaces.merge(format::reformat( + *Style, *Changed, + tooling::calculateRangesAfterReplacements(IncludeReplaces, {Range}), + File)); +} + +std::vector +ReplacementsToEdits(std::string_view code, const tooling::Replacements &Repls) { + std::vector ret; + int i = 0, line = 0, col = 0; + auto move = [&](int p) { + for (; i < p; i++) + if (code[i] == '\n') + line++, col = 0; + else { + if ((uint8_t)code[i] >= 128) { + while (128 <= (uint8_t)code[++i] && (uint8_t)code[i] < 192) + ; + i--; + } + col++; + } + }; + for (const auto &R : Repls) { + move(R.getOffset()); + int l = line, c = col; + move(R.getOffset() + R.getLength()); + ret.push_back({{{l, c}, {line, col}}, R.getReplacementText().str()}); + } + return ret; +} + +void Format(WorkingFile *wfile, tooling::Range range, lsRequestId id) { + std::string_view code = wfile->buffer_content; + auto ReplsOrErr = + FormatCode(code, wfile->filename, range); + if (ReplsOrErr) { + Out_TextDocumentFormatting out; + out.id = id; + out.result = ReplacementsToEdits(code, *ReplsOrErr); + pipeline::WriteStdout(formatting, out); + } else { + Out_Error err; + err.id = id; + err.error.code = lsErrorCodes::UnknownErrorCode; + err.error.message = llvm::toString(ReplsOrErr.takeError()); + pipeline::WriteStdout(kMethodType_Unknown, err); + } +} + +struct In_TextDocumentFormatting : public RequestInMessage { + MethodType GetMethodType() const override { return formatting; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsFormattingOptions options; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentFormatting::Params, textDocument, options); +MAKE_REFLECT_STRUCT(In_TextDocumentFormatting, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentFormatting); + +struct Handler_TextDocumentFormatting + : BaseMessageHandler { + MethodType GetMethodType() const override { return formatting; } + void Run(In_TextDocumentFormatting *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; + Format(wfile, {0, (unsigned)wfile->buffer_content.size()}, request->id); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentFormatting); + +struct In_TextDocumentOnTypeFormatting : public RequestInMessage { + MethodType GetMethodType() const override { return onTypeFormatting; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsPosition position; + std::string ch; + lsFormattingOptions options; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentOnTypeFormatting::Params, textDocument, + position, ch, options); +MAKE_REFLECT_STRUCT(In_TextDocumentOnTypeFormatting, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentOnTypeFormatting); + +struct Handler_TextDocumentOnTypeFormatting + : BaseMessageHandler { + MethodType GetMethodType() const override { return onTypeFormatting; } + void Run(In_TextDocumentOnTypeFormatting *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; + std::string_view code = wfile->buffer_content; + int pos = GetOffsetForPosition(params.position, code); + auto lbrace = code.find_last_of('{', pos); + if (lbrace == std::string::npos) + lbrace = pos; + Format(wfile, {(unsigned)lbrace, unsigned(pos - lbrace)}, request->id); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentOnTypeFormatting); + +struct In_TextDocumentRangeFormatting : public RequestInMessage { + MethodType GetMethodType() const override { return rangeFormatting; } + struct Params { + lsTextDocumentIdentifier textDocument; + lsRange range; + lsFormattingOptions options; + } params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentRangeFormatting::Params, textDocument, range, + options); +MAKE_REFLECT_STRUCT(In_TextDocumentRangeFormatting, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentRangeFormatting); + +struct Handler_TextDocumentRangeFormatting + : BaseMessageHandler { + MethodType GetMethodType() const override { return rangeFormatting; } + + void Run(In_TextDocumentRangeFormatting *request) override { + auto ¶ms = request->params; + QueryFile *file; + if (!FindFileOrFail(db, project, request->id, + params.textDocument.uri.GetPath(), &file)) + return; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!wfile) + return; + std::string_view code = wfile->buffer_content; + int begin = GetOffsetForPosition(params.range.start, code), + end = GetOffsetForPosition(params.range.end, code); + Format(wfile, {(unsigned)begin, unsigned(end - begin)}, request->id); + } +}; +REGISTER_MESSAGE_HANDLER(Handler_TextDocumentRangeFormatting); +} // namespace diff --git a/src/messages/textDocument_hover.cc b/src/messages/textDocument_hover.cc index 71dd0919..a368f846 100644 --- a/src/messages/textDocument_hover.cc +++ b/src/messages/textDocument_hover.cc @@ -36,6 +36,11 @@ GetHover(DB *db, LanguageId lang, SymbolRef sym, int file_id) { break; } } + if (!def && entity.def.size()) { + def = &entity.def[0]; + if (def->comments[0]) + comments = def->comments; + } if (def) { lsMarkedString m; m.language = LanguageIdentifier(lang); diff --git a/src/messages/textDocument_references.cc b/src/messages/textDocument_references.cc index 0c73a405..f09adfc8 100644 --- a/src/messages/textDocument_references.cc +++ b/src/messages/textDocument_references.cc @@ -16,10 +16,11 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; #include +using namespace ccls; + namespace { MethodType kMethodType = "textDocument/references"; @@ -66,13 +67,17 @@ struct Handler_TextDocumentReferences if (!FindFileOrFail(db, project, request->id, params.textDocument.uri.GetPath(), &file)) return; - - WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); - Out_TextDocumentReferences out; out.id = request->id; + WorkingFile *wfile = working_files->GetFileByFilename(file->def->path); + if (!file) { + pipeline::WriteStdout(kMethodType, out); + return; + } + bool container = g_config->xref.container; std::unordered_set seen_uses; + int line = params.position.line; for (SymbolRef sym : FindSymbolsAtLocation(wfile, file, params.position)) { // Found symbol. Return references. @@ -127,7 +132,7 @@ struct Handler_TextDocumentReferences // = 0, // use the current filename. std::string path; - if (params.position.line == 0) + if (line == 0 || line >= (int)wfile->buffer_lines.size() - 1) path = file->def->path; for (const IndexInclude &include : file->def->includes) if (include.line == params.position.line) { diff --git a/src/messages/textDocument_signatureHelp.cc b/src/messages/textDocument_signatureHelp.cc index 8799a542..1635cb35 100644 --- a/src/messages/textDocument_signatureHelp.cc +++ b/src/messages/textDocument_signatureHelp.cc @@ -13,49 +13,33 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" -using namespace ccls; -#include +#include + +using namespace ccls; +using namespace clang; namespace { MethodType kMethodType = "textDocument/signatureHelp"; -struct In_TextDocumentSignatureHelp : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsTextDocumentPositionParams params; -}; -MAKE_REFLECT_STRUCT(In_TextDocumentSignatureHelp, id, params); -REGISTER_IN_MESSAGE(In_TextDocumentSignatureHelp); - // Represents a parameter of a callable-signature. A parameter can // have a label and a doc-comment. struct lsParameterInformation { - // The label of this parameter. Will be shown in - // the UI. std::string label; - - // The human-readable doc-comment of this parameter. Will be shown - // in the UI but can be omitted. - std::optional documentation; + // Not available in clang + // std::optional documentation; }; -MAKE_REFLECT_STRUCT(lsParameterInformation, label, documentation); +MAKE_REFLECT_STRUCT(lsParameterInformation, label); // Represents the signature of something callable. A signature // can have a label, like a function-name, a doc-comment, and // a set of parameters. struct lsSignatureInformation { - // The label of this signature. Will be shown in - // the UI. std::string label; - - // The human-readable doc-comment of this signature. Will be shown - // in the UI but can be omitted. std::optional documentation; - - // The parameters of this signature. std::vector parameters; }; MAKE_REFLECT_STRUCT(lsSignatureInformation, label, documentation, parameters); @@ -64,30 +48,20 @@ MAKE_REFLECT_STRUCT(lsSignatureInformation, label, documentation, parameters); // callable. There can be multiple signature but only one // active and only one active parameter. struct lsSignatureHelp { - // One or more signatures. std::vector signatures; - - // The active signature. If omitted or the value lies outside the - // range of `signatures` the value defaults to zero or is ignored if - // `signatures.length === 0`. Whenever possible implementors should - // make an active decision about the active signature and shouldn't - // rely on a default value. - // In future version of the protocol this property might become - // mandantory to better express this. - std::optional activeSignature; - - // The active parameter of the active signature. If omitted or the value - // lies outside the range of `signatures[activeSignature].parameters` - // defaults to 0 if the active signature has parameters. If - // the active signature has no parameters it is ignored. - // In future version of the protocol this property might become - // mandantory to better express the active parameter if the - // active signature does have any. - std::optional activeParameter; + int activeSignature = 0; + int activeParameter = 0; }; MAKE_REFLECT_STRUCT(lsSignatureHelp, signatures, activeSignature, activeParameter); +struct In_TextDocumentSignatureHelp : public RequestInMessage { + MethodType GetMethodType() const override { return kMethodType; } + lsTextDocumentPositionParams params; +}; +MAKE_REFLECT_STRUCT(In_TextDocumentSignatureHelp, id, params); +REGISTER_IN_MESSAGE(In_TextDocumentSignatureHelp); + struct Out_TextDocumentSignatureHelp : public lsOutMessage { lsRequestId id; @@ -95,88 +69,164 @@ struct Out_TextDocumentSignatureHelp }; MAKE_REFLECT_STRUCT(Out_TextDocumentSignatureHelp, jsonrpc, id, result); -struct Handler_TextDocumentSignatureHelp : MessageHandler { +std::string BuildOptional(const CodeCompletionString &CCS, + std::vector &ls_params) { + std::string ret; + for (const auto &Chunk : CCS) { + switch (Chunk.Kind) { + case CodeCompletionString::CK_Optional: + ret += BuildOptional(*Chunk.Optional, ls_params); + break; + case CodeCompletionString::CK_Placeholder: + // A string that acts as a placeholder for, e.g., a function call + // argument. + // Intentional fallthrough here. + case CodeCompletionString::CK_CurrentParameter: { + // A piece of text that describes the parameter that corresponds to + // the code-completion location within a function call, message send, + // macro invocation, etc. + ret += Chunk.Text; + ls_params.push_back(lsParameterInformation{Chunk.Text}); + break; + } + case CodeCompletionString::CK_VerticalSpace: + break; + default: + ret += Chunk.Text; + break; + } + } + return ret; +} + +class SignatureHelpConsumer : public CodeCompleteConsumer { + std::shared_ptr Alloc; + CodeCompletionTUInfo CCTUInfo; +public: + bool from_cache; + lsSignatureHelp ls_sighelp; + SignatureHelpConsumer(const clang::CodeCompleteOptions &CCOpts, + bool from_cache) + : CodeCompleteConsumer(CCOpts, false), + Alloc(std::make_shared()), + CCTUInfo(Alloc), from_cache(from_cache) {} + void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, + OverloadCandidate *Candidates, + unsigned NumCandidates +#if LLVM_VERSION_MAJOR >= 8 + , + SourceLocation OpenParLoc +#endif + ) override { + ls_sighelp.activeParameter = (int)CurrentArg; + for (unsigned i = 0; i < NumCandidates; i++) { + OverloadCandidate Cand = Candidates[i]; + // We want to avoid showing instantiated signatures, because they may be + // long in some cases (e.g. when 'T' is substituted with 'std::string', we + // would get 'std::basic_string'). + if (auto *Func = Cand.getFunction()) + if (auto *Pattern = Func->getTemplateInstantiationPattern()) + Cand = OverloadCandidate(Pattern); + + const auto *CCS = + Cand.CreateSignatureString(CurrentArg, S, *Alloc, CCTUInfo, true); + + const char *ret_type = nullptr; + lsSignatureInformation &ls_sig = ls_sighelp.signatures.emplace_back(); +#if LLVM_VERSION_MAJOR >= 8 + const RawComment *RC = getCompletionComment(S.getASTContext(), Cand.getFunction()); + ls_sig.documentation = RC ? RC->getBriefText(S.getASTContext()) : ""; +#endif + for (const auto &Chunk : *CCS) + switch (Chunk.Kind) { + case CodeCompletionString::CK_ResultType: + ret_type = Chunk.Text; + break; + case CodeCompletionString::CK_Placeholder: + case CodeCompletionString::CK_CurrentParameter: { + ls_sig.label += Chunk.Text; + ls_sig.parameters.push_back(lsParameterInformation{Chunk.Text}); + break; + } + case CodeCompletionString::CK_Optional: + ls_sig.label += BuildOptional(*Chunk.Optional, ls_sig.parameters); + break; + case CodeCompletionString::CK_VerticalSpace: + break; + default: + ls_sig.label += Chunk.Text; + break; + } + if (ret_type) { + ls_sig.label += " -> "; + ls_sig.label += ret_type; + } + } + std::sort( + ls_sighelp.signatures.begin(), ls_sighelp.signatures.end(), + [](const lsSignatureInformation &l, const lsSignatureInformation &r) { + if (l.parameters.size() != r.parameters.size()) + return l.parameters.size() < r.parameters.size(); + if (l.label.size() != r.label.size()) + return l.label.size() < r.label.size(); + return l.label < r.label; + }); + } + + CodeCompletionAllocator &getAllocator() override { return *Alloc; } + CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } +}; + +struct Handler_TextDocumentSignatureHelp + : BaseMessageHandler { MethodType GetMethodType() const override { return kMethodType; } - void Run(std::unique_ptr message) override { - auto request = static_cast(message.get()); - lsTextDocumentPositionParams ¶ms = request->params; - WorkingFile *file = - working_files->GetFileByFilename(params.textDocument.uri.GetPath()); - std::string search; - int active_param = 0; - if (file) { - lsPosition completion_position; - search = file->FindClosestCallNameInBuffer(params.position, &active_param, - &completion_position); - params.position = completion_position; + void Run(In_TextDocumentSignatureHelp *request) override { + static CompleteConsumerCache cache; + + auto ¶ms = request->params; + std::string path = params.textDocument.uri.GetPath(); + if (WorkingFile *file = working_files->GetFileByFilename(path)) { + std::string completion_text; + lsPosition end_pos = params.position; + params.position = file->FindStableCompletionSource( + request->params.position, &completion_text, &end_pos); } - if (search.empty()) - return; - - ClangCompleteManager::OnComplete callback = std::bind( - [this](InMessage *message, std::string search, int active_param, - const std::vector &results, - bool is_cached_result) { - auto msg = static_cast(message); + CompletionManager::OnComplete callback = + [id = request->id, + params = request->params](CodeCompleteConsumer *OptConsumer) { + if (!OptConsumer) + return; + auto *Consumer = static_cast(OptConsumer); Out_TextDocumentSignatureHelp out; - out.id = msg->id; - - for (auto &result : results) { - if (result.label != search) - continue; - - lsSignatureInformation signature; - signature.label = result.detail; - for (auto ¶meter : result.parameters_) { - lsParameterInformation ls_param; - ls_param.label = parameter; - signature.parameters.push_back(ls_param); - } - out.result.signatures.push_back(signature); - } - - // Prefer the signature with least parameter count but still larger - // than active_param. - out.result.activeSignature = 0; - if (out.result.signatures.size()) { - size_t num_parameters = SIZE_MAX; - for (size_t i = 0; i < out.result.signatures.size(); ++i) { - size_t t = out.result.signatures[i].parameters.size(); - if (active_param < t && t < num_parameters) { - out.result.activeSignature = int(i); - num_parameters = t; - } - } - } - - // Set signature to what we parsed from the working file. - out.result.activeParameter = active_param; - + out.id = id; + out.result = Consumer->ls_sighelp; pipeline::WriteStdout(kMethodType, out); - - if (!is_cached_result) { - signature_cache->WithLock([&]() { - signature_cache->cached_path_ = - msg->params.textDocument.uri.GetPath(); - signature_cache->cached_completion_position_ = - msg->params.position; - signature_cache->cached_results_ = results; + if (!Consumer->from_cache) { + std::string path = params.textDocument.uri.GetPath(); + cache.WithLock([&]() { + cache.path = path; + cache.position = params.position; + cache.result = Consumer->ls_sighelp; }); } + }; - delete message; - }, - message.release(), search, active_param, std::placeholders::_1, - std::placeholders::_2); - - if (signature_cache->IsCacheValid(params)) { - signature_cache->WithLock([&]() { - callback(signature_cache->cached_results_, true /*is_cached_result*/); - }); + CodeCompleteOptions CCOpts; + CCOpts.IncludeGlobals = false; + CCOpts.IncludeMacros = false; + CCOpts.IncludeBriefComments = false; + if (cache.IsCacheValid(params)) { + SignatureHelpConsumer Consumer(CCOpts, true); + cache.WithLock([&]() { Consumer.ls_sighelp = cache.result; }); + callback(&Consumer); } else { - clang_complete->CodeComplete(request->id, params, std::move(callback)); + clang_complete->completion_request_.PushBack( + std::make_unique( + request->id, params.textDocument, params.position, + std::make_unique(CCOpts, false), CCOpts, + callback)); } } }; diff --git a/src/messages/textDocument_typeDefinition.cc b/src/messages/textDocument_typeDefinition.cc index ff1383f7..30786850 100644 --- a/src/messages/textDocument_typeDefinition.cc +++ b/src/messages/textDocument_typeDefinition.cc @@ -42,32 +42,40 @@ struct Handler_TextDocumentTypeDefinition QueryFile *file; if (!FindFileOrFail(db, project, request->id, request->params.textDocument.uri.GetPath(), &file, - nullptr)) { + nullptr)) return; - } WorkingFile *working_file = working_files->GetFileByFilename(file->def->path); Out_TextDocumentTypeDefinition out; out.id = request->id; + auto Add = [&](const QueryType &type) { + for (const auto &def : type.def) + if (def.spell) { + if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell, + g_config->xref.container)) + out.result.push_back(*ls_loc); + } + if (out.result.empty()) + for (const DeclRef &dr : type.declarations) + if (auto ls_loc = GetLsLocationEx(db, working_files, dr, + g_config->xref.container)) + out.result.push_back(*ls_loc); + }; for (SymbolRef sym : FindSymbolsAtLocation(working_file, file, request->params.position)) { - Usr usr = sym.usr; switch (sym.kind) { case SymbolKind::Var: { const QueryVar::Def *def = db->GetVar(sym).AnyDef(); - if (!def || !def->type) - continue; - usr = def->type; - [[fallthrough]]; + if (def && def->type) + Add(db->Type(def->type)); + break; } case SymbolKind::Type: { - QueryType &type = db->Type(usr); - for (const auto &def : type.def) - if (def.spell) { - if (auto ls_loc = GetLsLocationEx(db, working_files, *def.spell, - g_config->xref.container)) - out.result.push_back(*ls_loc); + for (auto &def : db->GetType(sym).def) + if (def.alias_of) { + Add(db->Type(def.alias_of)); + break; } break; } diff --git a/src/messages/workspace_didChangeConfiguration.cc b/src/messages/workspace_didChangeConfiguration.cc index eb5b2d88..9b9ba474 100644 --- a/src/messages/workspace_didChangeConfiguration.cc +++ b/src/messages/workspace_didChangeConfiguration.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" #include "project.h" diff --git a/src/messages/workspace_didChangeWatchedFiles.cc b/src/messages/workspace_didChangeWatchedFiles.cc index c25078b9..d338cfc8 100644 --- a/src/messages/workspace_didChangeWatchedFiles.cc +++ b/src/messages/workspace_didChangeWatchedFiles.cc @@ -13,7 +13,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#include "clang_complete.h" +#include "clang_complete.hh" #include "message_handler.h" #include "pipeline.hh" #include "project.h" @@ -54,26 +54,22 @@ struct Handler_WorkspaceDidChangeWatchedFiles void Run(In_WorkspaceDidChangeWatchedFiles *request) override { for (lsFileEvent &event : request->params.changes) { std::string path = event.uri.GetPath(); - Project::Entry entry; - { - std::lock_guard lock(project->mutex_); - auto it = project->absolute_path_to_entry_index_.find(path); - if (it == project->absolute_path_to_entry_index_.end()) - continue; - entry = project->entries[it->second]; - } - bool is_interactive = - working_files->GetFileByFilename(entry.filename) != nullptr; + IndexMode mode = working_files->GetFileByFilename(path) + ? IndexMode::Normal + : IndexMode::NonInteractive; switch (event.type) { case lsFileChangeType::Created: case lsFileChangeType::Changed: { - pipeline::Index(path, entry.args, is_interactive); - if (is_interactive) + pipeline::Index(path, {}, mode); + if (mode == IndexMode::Normal) clang_complete->NotifySave(path); + else + clang_complete->OnClose(path); break; } case lsFileChangeType::Deleted: - pipeline::Index(path, entry.args, is_interactive); + pipeline::Index(path, {}, mode); + clang_complete->OnClose(path); break; } } diff --git a/src/messages/workspace_executeCommand.cc b/src/messages/workspace_executeCommand.cc deleted file mode 100644 index a7fc764d..00000000 --- a/src/messages/workspace_executeCommand.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright 2017-2018 ccls Authors - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -==============================================================================*/ - -#include "lsp_code_action.h" -#include "message_handler.h" -#include "pipeline.hh" -#include "query_utils.h" -using namespace ccls; - -namespace { -MethodType kMethodType = "workspace/executeCommand"; - -struct In_WorkspaceExecuteCommand : public RequestInMessage { - MethodType GetMethodType() const override { return kMethodType; } - lsCommand params; -}; -MAKE_REFLECT_STRUCT(In_WorkspaceExecuteCommand, id, params); -REGISTER_IN_MESSAGE(In_WorkspaceExecuteCommand); - -struct Out_WorkspaceExecuteCommand - : public lsOutMessage { - lsRequestId id; - std::variant, CommandArgs> result; -}; -MAKE_REFLECT_STRUCT(Out_WorkspaceExecuteCommand, jsonrpc, id, result); - -struct Handler_WorkspaceExecuteCommand - : BaseMessageHandler { - MethodType GetMethodType() const override { return kMethodType; } - void Run(In_WorkspaceExecuteCommand *request) override { - const auto ¶ms = request->params; - Out_WorkspaceExecuteCommand out; - out.id = request->id; - if (params.command == "ccls._applyFixIt") { - } else if (params.command == "ccls._autoImplement") { - } else if (params.command == "ccls._insertInclude") { - } else if (params.command == "ccls.showReferences") { - out.result = params.arguments.locations; - } - - pipeline::WriteStdout(kMethodType, out); - } -}; -REGISTER_MESSAGE_HANDLER(Handler_WorkspaceExecuteCommand); - -} // namespace diff --git a/src/messages/workspace_symbol.cc b/src/messages/workspace_symbol.cc index 2449e072..4758b38e 100644 --- a/src/messages/workspace_symbol.cc +++ b/src/messages/workspace_symbol.cc @@ -17,13 +17,14 @@ limitations under the License. #include "message_handler.h" #include "pipeline.hh" #include "query_utils.h" -using namespace ccls; #include #include #include #include +using namespace ccls; + namespace { MethodType kMethodType = "workspace/symbol"; @@ -31,8 +32,7 @@ MethodType kMethodType = "workspace/symbol"; bool AddSymbol( DB *db, WorkingFiles *working_files, SymbolIdx sym, bool use_detailed, std::vector> *result) { - std::optional info = - GetSymbolInfo(db, working_files, sym, true); + std::optional info = GetSymbolInfo(db, sym, true); if (!info) return false; diff --git a/src/pipeline.cc b/src/pipeline.cc index 30c3e978..c61469c0 100644 --- a/src/pipeline.cc +++ b/src/pipeline.cc @@ -15,71 +15,65 @@ limitations under the License. #include "pipeline.hh" -#include "clang_complete.h" +#include "clang_complete.hh" #include "config.h" #include "include_complete.h" #include "log.hh" #include "lsp.h" +#include "match.h" #include "message_handler.h" #include "pipeline.hh" #include "platform.h" #include "project.h" #include "query_utils.h" -#include #include #include using namespace llvm; #include +#include +#include #include #ifndef _WIN32 #include #endif -void DiagnosticsPublisher::Init() { - frequencyMs_ = g_config->diagnostics.frequencyMs; - match_ = std::make_unique(g_config->diagnostics.whitelist, - g_config->diagnostics.blacklist); +void VFS::Clear() { + std::lock_guard lock(mutex); + state.clear(); } -void DiagnosticsPublisher::Publish(WorkingFiles *working_files, - std::string path, - std::vector diagnostics) { - bool good = true; - // Cache diagnostics so we can show fixits. - working_files->DoActionOnFile(path, [&](WorkingFile *working_file) { - if (working_file) { - good = working_file->diagnostics_.empty(); - working_file->diagnostics_ = diagnostics; - } - }); +bool VFS::Loaded(const std::string &path) { + std::lock_guard lock(mutex); + return state[path].loaded; +} - int64_t now = - std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()) - .count(); - if (frequencyMs_ >= 0 && - (nextPublish_ <= now || (!good && diagnostics.empty())) && - match_->IsMatch(path)) { - nextPublish_ = now + frequencyMs_; - - Out_TextDocumentPublishDiagnostics out; - out.params.uri = lsDocumentUri::FromPath(path); - out.params.diagnostics = diagnostics; - ccls::pipeline::WriteStdout(kMethodType_TextDocumentPublishDiagnostics, - out); - } +bool VFS::Stamp(const std::string &path, int64_t ts, int step) { + std::lock_guard lock(mutex); + State &st = state[path]; + if (st.timestamp < ts || (st.timestamp == ts && st.step < step)) { + st.timestamp = ts; + st.step = step; + return true; + } else + return false; } namespace ccls::pipeline { + +std::atomic loaded_ts = ATOMIC_VAR_INIT(0), + pending_index_requests = ATOMIC_VAR_INIT(0); +int64_t tick = 0; + namespace { struct Index_Request { std::string path; - std::vector args; - bool is_interactive; + std::vector args; + IndexMode mode; lsRequestId id; + int64_t ts = tick++; }; struct Stdout_Request { @@ -95,25 +89,33 @@ ThreadedQueue *index_request; ThreadedQueue *on_indexed; ThreadedQueue *for_stdout; +struct InMemoryIndexFile { + std::string content; + IndexFile index; +}; +std::shared_mutex g_index_mutex; +std::unordered_map g_index; + bool CacheInvalid(VFS *vfs, IndexFile *prev, const std::string &path, - const std::vector &args, + const std::vector &args, const std::optional &from) { { std::lock_guard lock(vfs->mutex); - if (prev->last_write_time < vfs->state[path].timestamp) { + if (prev->mtime < vfs->state[path].timestamp) { LOG_S(INFO) << "timestamp changed for " << path << (from ? " (via " + *from + ")" : std::string()); return true; } } - if (prev->args != args) { + bool changed = prev->args.size() != args.size(); + for (size_t i = 0; !changed && i < args.size(); i++) + if (strcmp(prev->args[i], args[i])) + changed = true; + if (changed) LOG_S(INFO) << "args changed for " << path << (from ? " (via " + *from + ")" : std::string()); - return true; - } - - return false; + return changed; }; std::string AppendSerializationFormat(const std::string &base) { @@ -127,12 +129,13 @@ std::string AppendSerializationFormat(const std::string &base) { std::string GetCachePath(const std::string &source_file) { std::string cache_file; - size_t len = g_config->projectRoot.size(); + auto len = g_config->projectRoot.size(); if (StartsWith(source_file, g_config->projectRoot)) { - cache_file = EscapeFileName(g_config->projectRoot) + + cache_file = EscapeFileName(g_config->projectRoot.substr(0, len - 1)) + '/' + EscapeFileName(source_file.substr(len)); } else { - cache_file = '@' + EscapeFileName(g_config->projectRoot) + + cache_file = '@' + + EscapeFileName(g_config->projectRoot.substr(0, len - 1)) + '/' + EscapeFileName(source_file); } @@ -140,6 +143,14 @@ std::string GetCachePath(const std::string &source_file) { } std::unique_ptr RawCacheLoad(const std::string &path) { + if (g_config->cacheDirectory.empty()) { + std::shared_lock lock(g_index_mutex); + auto it = g_index.find(path); + if (it == g_index.end()) + return nullptr; + return std::make_unique(it->second.index); + } + std::string cache_path = GetCachePath(path); std::optional file_content = ReadContent(cache_path); std::optional serialized_indexed_content = @@ -152,12 +163,22 @@ std::unique_ptr RawCacheLoad(const std::string &path) { IndexFile::kMajorVersion); } -bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, - Project *project, VFS *vfs) { +std::mutex &GetFileMutex(const std::string &path) { + const int N_MUTEXES = 256; + static std::mutex mutexes[N_MUTEXES]; + return mutexes[std::hash()(path) % N_MUTEXES]; +} + +bool Indexer_Parse(CompletionManager *completion, WorkingFiles *wfiles, + Project *project, VFS *vfs, const GroupMatch &matcher) { std::optional opt_request = index_request->TryPopFront(); if (!opt_request) return false; auto &request = *opt_request; + bool loud = request.mode != IndexMode::OnChange; + struct RAII { + ~RAII() { pending_index_requests--; } + } raii; // Dummy one to trigger refresh semantic highlight. if (request.path.empty()) { @@ -167,125 +188,165 @@ bool Indexer_Parse(DiagnosticsPublisher *diag_pub, WorkingFiles *working_files, return false; } - Project::Entry entry; - { - std::lock_guard lock(project->mutex_); - auto it = project->absolute_path_to_entry_index_.find(request.path); - if (it != project->absolute_path_to_entry_index_.end()) - entry = project->entries[it->second]; - else { - entry.filename = request.path; - entry.args = request.args; - } + if (!matcher.IsMatch(request.path)) { + LOG_IF_S(INFO, loud) << "skip " << request.path; + return false; } + + Project::Entry entry = project->FindEntry(request.path, true); + if (request.args.size()) + entry.args = request.args; std::string path_to_index = entry.filename; std::unique_ptr prev; - // Try to load the file from cache. std::optional write_time = LastWriteTime(path_to_index); if (!write_time) return true; - int reparse = vfs->Stamp(path_to_index, *write_time); - if (!vfs->Mark(path_to_index, g_thread_id, 1) && !reparse) - return true; - - prev = RawCacheLoad(path_to_index); - if (!prev) - reparse = 2; - else { - if (CacheInvalid(vfs, prev.get(), path_to_index, entry.args, std::nullopt)) + int reparse = vfs->Stamp(path_to_index, *write_time, 0); + if (request.path != path_to_index) { + std::optional mtime1 = LastWriteTime(request.path); + if (!mtime1) + return true; + if (vfs->Stamp(request.path, *mtime1, 0)) reparse = 2; - int reparseForDep = g_config->index.reparseForDependency; - if (reparseForDep > 1 || (reparseForDep == 1 && !Project::loaded)) - for (const auto &dep : prev->dependencies) { - if (auto write_time1 = LastWriteTime(dep.first().str())) { - if (dep.second < *write_time1) { - reparse = 2; - std::lock_guard lock(vfs->mutex); - vfs->state[dep.first().str()].stage = 0; - } - } else - reparse = 2; - } } - - // Grab the ownership - if (reparse) { - std::lock_guard lock(vfs->mutex); - vfs->state[path_to_index].owner = g_thread_id; - vfs->state[path_to_index].stage = 0; + if (g_config->index.onChange) { + reparse = 2; + std::lock_guard lock(vfs->mutex); + vfs->state[path_to_index].step = 0; + if (request.path != path_to_index) + vfs->state[request.path].step = 0; } - - if (reparse < 2) { - LOG_S(INFO) << "load cache for " << path_to_index; - auto dependencies = prev->dependencies; - if (reparse) { - IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); - on_indexed->PushBack(std::move(update), request.is_interactive); - } - for (const auto &dep : dependencies) - if (vfs->Mark(dep.first().str(), 0, 2) && - (prev = RawCacheLoad(dep.first().str()))) { - IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); - on_indexed->PushBack(std::move(update), request.is_interactive); - } + bool track = g_config->index.trackDependency > 1 || + (g_config->index.trackDependency == 1 && request.ts < loaded_ts); + if (!reparse && !track) return true; + + if (reparse < 2) + do { + std::unique_lock lock(GetFileMutex(path_to_index)); + prev = RawCacheLoad(path_to_index); + if (!prev || CacheInvalid(vfs, prev.get(), path_to_index, entry.args, + std::nullopt)) + break; + if (track) + for (const auto &dep : prev->dependencies) { + if (auto mtime1 = LastWriteTime(dep.first.val().str())) { + if (dep.second < *mtime1) { + reparse = 2; + break; + } + } else { + reparse = 2; + break; + } + } + if (reparse == 0) + return true; + if (reparse == 2) + break; + + if (vfs->Loaded(path_to_index)) + return true; + LOG_S(INFO) << "load cache for " << path_to_index; + auto dependencies = prev->dependencies; + IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); + { + std::lock_guard lock1(vfs->mutex); + vfs->state[path_to_index].loaded = true; + } + lock.unlock(); + + for (const auto &dep : dependencies) { + std::string path = dep.first.val().str(); + if (!vfs->Stamp(path, dep.second, 1)) + continue; + std::lock_guard lock1(GetFileMutex(path)); + prev = RawCacheLoad(path); + if (!prev) + continue; + { + std::lock_guard lock2(vfs->mutex); + VFS::State &st = vfs->state[path]; + if (st.loaded) + continue; + st.loaded = true; + st.timestamp = prev->mtime; + } + IndexUpdate update = IndexUpdate::CreateDelta(nullptr, prev.get()); + on_indexed->PushBack(std::move(update), + request.mode != IndexMode::NonInteractive); + if (entry.id >= 0) { + std::lock_guard lock2(project->mutex_); + project->path_to_entry_index[path] = entry.id; + } + } + return true; + } while (0); + + LOG_IF_S(INFO, loud) << "parse " << path_to_index; + + std::vector> remapped; + if (g_config->index.onChange) { + std::string content = wfiles->GetContent(path_to_index); + if (content.size()) + remapped.emplace_back(path_to_index, content); } + bool ok; + auto indexes = idx::Index(completion, wfiles, vfs, entry.directory, + path_to_index, entry.args, remapped, ok); - LOG_S(INFO) << "parse " << path_to_index; - - auto indexes = - idx::Index(vfs, entry.directory, path_to_index, entry.args, {}); - - if (indexes.empty()) { - if (g_config->index.enabled && request.id.Valid()) { + if (!ok) { + if (request.id.Valid()) { Out_Error out; out.id = request.id; out.error.code = lsErrorCodes::InternalError; out.error.message = "Failed to index " + path_to_index; pipeline::WriteStdout(kMethodType_Unknown, out); } - vfs->Reset(path_to_index); return true; } for (std::unique_ptr &curr : indexes) { - // Only emit diagnostics for non-interactive sessions, which makes it easier - // to identify indexing problems. For interactive sessions, diagnostics are - // handled by code completion. - if (!request.is_interactive) - diag_pub->Publish(working_files, curr->path, curr->diagnostics_); - std::string path = curr->path; - if (!(vfs->Stamp(path, curr->last_write_time) || path == path_to_index)) + if (!matcher.IsMatch(path)) { + LOG_IF_S(INFO, loud) << "skip index for " << path; continue; - LOG_S(INFO) << "emit index for " << path; - prev = RawCacheLoad(path); + } - // Write current index to disk if requested. - LOG_S(INFO) << "store index for " << path; + LOG_IF_S(INFO, loud) << "store index for " << path << " (delta: " << !!prev + << ")"; { - static Timer timer("write", "store index"); - timer.startTimer(); - std::string cache_path = GetCachePath(path); - WriteToFile(cache_path, curr->file_contents); - WriteToFile(AppendSerializationFormat(cache_path), - Serialize(g_config->cacheFormat, *curr)); - timer.stopTimer(); + std::lock_guard lock(GetFileMutex(path)); + if (vfs->Loaded(path)) + prev = RawCacheLoad(path); + else + prev.reset(); + if (g_config->cacheDirectory.empty()) { + std::lock_guard lock(g_index_mutex); + auto it = g_index.insert_or_assign( + path, InMemoryIndexFile{curr->file_contents, *curr}); + std::string().swap(it.first->second.index.file_contents); + } else { + std::string cache_path = GetCachePath(path); + WriteToFile(cache_path, curr->file_contents); + WriteToFile(AppendSerializationFormat(cache_path), + Serialize(g_config->cacheFormat, *curr)); + } + on_indexed->PushBack(IndexUpdate::CreateDelta(prev.get(), curr.get()), + request.mode != IndexMode::NonInteractive); + { + std::lock_guard lock1(vfs->mutex); + vfs->state[path].loaded = true; + } + if (entry.id >= 0) { + std::lock_guard lock(project->mutex_); + for (auto &dep : curr->dependencies) + project->path_to_entry_index[dep.first.val().str()] = entry.id; + } } - - vfs->Reset(path); - if (entry.id >= 0) { - std::lock_guard lock(project->mutex_); - for (auto &dep : curr->dependencies) - project->absolute_path_to_entry_index_[dep.first()] = entry.id; - } - - // Build delta update. - IndexUpdate update = IndexUpdate::CreateDelta(prev.get(), curr.get()); - LOG_S(INFO) << "built index for " << path << " (is_delta=" << !!prev << ")"; - - on_indexed->PushBack(std::move(update), request.is_interactive); } return true; @@ -305,17 +366,16 @@ void Init() { for_stdout = new ThreadedQueue(stdout_waiter); } -void Indexer_Main(DiagnosticsPublisher *diag_pub, VFS *vfs, Project *project, - WorkingFiles *working_files) { +void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, + WorkingFiles *wfiles) { + GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist); while (true) - if (!Indexer_Parse(diag_pub, working_files, project, vfs)) + if (!Indexer_Parse(completion, wfiles, project, vfs, matcher)) indexer_waiter->Wait(index_request); } -void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, - WorkingFiles *working_files, IndexUpdate *update) { +void Main_OnIndexed(DB *db, WorkingFiles *working_files, IndexUpdate *update) { if (update->refresh) { - Project::loaded = true; LOG_S(INFO) << "loaded project. Refresh semantic highlight for all working file."; std::lock_guard lock(working_files->files_mutex); @@ -324,7 +384,7 @@ void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, if (db->name2file_id.find(filename) == db->name2file_id.end()) continue; QueryFile *file = &db->files[db->name2file_id[filename]]; - EmitSemanticHighlighting(db, semantic_cache, f.get(), file); + EmitSemanticHighlighting(db, f.get(), file); } return; } @@ -337,13 +397,14 @@ void Main_OnIndexed(DB *db, SemanticHighlightSymbolCache *semantic_cache, // Update indexed content, skipped ranges, and semantic highlighting. if (update->files_def_update) { auto &def_u = *update->files_def_update; - LOG_S(INFO) << "apply index for " << def_u.first.path; - if (WorkingFile *working_file = + if (WorkingFile *wfile = working_files->GetFileByFilename(def_u.first.path)) { - working_file->SetIndexContent(def_u.second); - EmitSkippedRanges(working_file, def_u.first.skipped_ranges); - EmitSemanticHighlighting(db, semantic_cache, working_file, - &db->files[update->file_id]); + // FIXME With index.onChange: true, use buffer_content only for + // request.path + wfile->SetIndexContent(g_config->index.onChange ? wfile->buffer_content + : def_u.second); + EmitSkippedRanges(wfile, def_u.first.skipped_ranges); + EmitSemanticHighlighting(db, wfile, &db->files[update->file_id]); } } } @@ -413,15 +474,17 @@ void LaunchStdout() { void MainLoop() { Project project; - SemanticHighlightSymbolCache semantic_cache; WorkingFiles working_files; VFS vfs; - DiagnosticsPublisher diag_pub; - ClangCompleteManager clang_complete( + CompletionManager clang_complete( &project, &working_files, [&](std::string path, std::vector diagnostics) { - diag_pub.Publish(&working_files, path, diagnostics); + Out_TextDocumentPublishDiagnostics out; + out.params.uri = lsDocumentUri::FromPath(path); + out.params.diagnostics = diagnostics; + ccls::pipeline::WriteStdout(kMethodType_TextDocumentPublishDiagnostics, + out); }, [](lsRequestId id) { if (id.Valid()) { @@ -435,28 +498,19 @@ void MainLoop() { }); IncludeComplete include_complete(&project); - auto global_code_complete_cache = std::make_unique(); - auto non_global_code_complete_cache = std::make_unique(); - auto signature_cache = std::make_unique(); DB db; // Setup shared references. for (MessageHandler *handler : *MessageHandler::message_handlers) { handler->db = &db; - handler->waiter = indexer_waiter; handler->project = &project; - handler->diag_pub = &diag_pub; handler->vfs = &vfs; - handler->semantic_cache = &semantic_cache; handler->working_files = &working_files; handler->clang_complete = &clang_complete; handler->include_complete = &include_complete; - handler->global_code_complete_cache = global_code_complete_cache.get(); - handler->non_global_code_complete_cache = - non_global_code_complete_cache.get(); - handler->signature_cache = signature_cache.get(); } + bool has_indexed = false; while (true) { std::vector> messages = on_request->DequeueAll(); bool did_work = messages.size(); @@ -473,27 +527,42 @@ void MainLoop() { LOG_S(ERROR) << "No handler for " << message->GetMethodType(); } - for (int i = 80; i--;) { + bool indexed = false; + for (int i = 20; i--;) { std::optional update = on_indexed->TryPopFront(); if (!update) break; did_work = true; - Main_OnIndexed(&db, &semantic_cache, &working_files, &*update); + indexed = true; + Main_OnIndexed(&db, &working_files, &*update); } - if (!did_work) { - FreeUnusedMemory(); + if (did_work) + has_indexed |= indexed; + else { + if (has_indexed) { + FreeUnusedMemory(); + has_indexed = false; + } main_waiter->Wait(on_indexed, on_request); } } } -void Index(const std::string &path, const std::vector &args, - bool interactive, lsRequestId id) { - index_request->PushBack({path, args, interactive, id}, interactive); +void Index(const std::string &path, const std::vector &args, + IndexMode mode, lsRequestId id) { + pending_index_requests++; + index_request->PushBack({path, args, mode, id}, mode != IndexMode::NonInteractive); } -std::optional LoadCachedFileContents(const std::string &path) { +std::optional LoadIndexedContent(const std::string &path) { + if (g_config->cacheDirectory.empty()) { + std::shared_lock lock(g_index_mutex); + auto it = g_index.find(path); + if (it == g_index.end()) + return {}; + return it->second.content; + } return ReadContent(GetCachePath(path)); } diff --git a/src/pipeline.hh b/src/pipeline.hh index d3c7dcf4..b4cc514b 100644 --- a/src/pipeline.hh +++ b/src/pipeline.hh @@ -4,44 +4,54 @@ #include "method.h" #include "query.h" +#include +#include #include #include #include +struct CompletionManager; struct GroupMatch; struct VFS; struct Project; struct WorkingFiles; struct lsBaseOutMessage; -class DiagnosticsPublisher { - std::unique_ptr match_; - int64_t nextPublish_ = 0; - int frequencyMs_; +struct VFS { + struct State { + int64_t timestamp; + int step; + bool loaded; + }; + std::unordered_map state; + std::mutex mutex; - public: - void Init(); - void Publish(WorkingFiles* working_files, - std::string path, - std::vector diagnostics); + void Clear(); + bool Loaded(const std::string &path); + bool Stamp(const std::string &path, int64_t ts, int step); }; -namespace ccls::pipeline { +namespace ccls { +enum class IndexMode { + NonInteractive, + OnChange, + Normal, +}; +namespace pipeline { +extern std::atomic loaded_ts, pending_index_requests; +extern int64_t tick; void Init(); void LaunchStdin(); void LaunchStdout(); -void Indexer_Main(DiagnosticsPublisher* diag_pub, - VFS* vfs, - Project* project, - WorkingFiles* working_files); +void Indexer_Main(CompletionManager *completion, VFS *vfs, Project *project, + WorkingFiles *wfiles); void MainLoop(); -void Index(const std::string& path, - const std::vector& args, - bool is_interactive, - lsRequestId id = {}); +void Index(const std::string &path, const std::vector &args, + IndexMode mode, lsRequestId id = {}); -std::optional LoadCachedFileContents(const std::string& path); -void WriteStdout(MethodType method, lsBaseOutMessage& response); -} +std::optional LoadIndexedContent(const std::string& path); +void WriteStdout(MethodType method, lsBaseOutMessage &response); +} // namespace pipeline +} // namespace ccls diff --git a/src/platform_posix.cc b/src/platform_posix.cc index 4f48896c..1d2d59a9 100644 --- a/src/platform_posix.cc +++ b/src/platform_posix.cc @@ -113,7 +113,7 @@ std::string NormalizePath(const std::string &path) { void FreeUnusedMemory() { #ifdef __GLIBC__ - malloc_trim(0); + malloc_trim(4 * 1024 * 1024); #endif } diff --git a/src/platform_win.cc b/src/platform_win.cc index be03055c..3acbe7e2 100644 --- a/src/platform_win.cc +++ b/src/platform_win.cc @@ -35,14 +35,19 @@ std::string NormalizePath(const std::string &path) { TCHAR buffer[MAX_PATH] = TEXT(""); TCHAR **lpp_part = {NULL}; + std::string result; retval = GetFullPathName(path.c_str(), MAX_PATH, buffer, lpp_part); // fail, return original if (retval == 0) - return path; + result = path; + else + result = buffer; - std::string result = buffer; std::replace(result.begin(), result.end(), '\\', '/'); - // std::transform(result.begin(), result.end(), result.begin(), ::tolower); + // Normalize drive letter. + if (result.size() > 1 && result[0] >= 'a' && result[0] <= 'z' && + result[1] == ':') + result[0] = toupper(result[0]); return result; } diff --git a/src/position.h b/src/position.h index 110676ca..5ff53515 100644 --- a/src/position.h +++ b/src/position.h @@ -40,6 +40,7 @@ struct Position { return line < o.line; return column < o.column; } + bool operator<=(const Position &o) const { return !(o < *this); } }; MAKE_HASHABLE(Position, t.line, t.column); diff --git a/src/project.cc b/src/project.cc index 581a8a1b..1278e1e4 100644 --- a/src/project.cc +++ b/src/project.cc @@ -15,7 +15,6 @@ limitations under the License. #include "project.h" -#include "clang_utils.h" #include "filesystem.hh" #include "language.h" #include "log.hh" @@ -25,17 +24,14 @@ limitations under the License. #include "serializers/json.h" #include "utils.h" #include "working_files.h" -using namespace ccls; #include #include #include #include -#include +#include #include #include -using namespace clang; -using namespace llvm; #include @@ -43,10 +39,14 @@ using namespace llvm; #include #endif -#include +#include #include #include +using namespace ccls; +using namespace clang; +using namespace llvm; + namespace { enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand }; @@ -54,7 +54,6 @@ enum class ProjectMode { CompileCommandsJson, DotCcls, ExternalCommand }; struct ProjectConfig { std::unordered_set quote_dirs; std::unordered_set angle_dirs; - std::vector extra_flags; std::string project_dir; ProjectMode mode = ProjectMode::CompileCommandsJson; }; @@ -66,15 +65,6 @@ enum OptionClass { Separate, }; -std::string ResolveIfRelative(const std::string &directory, - const std::string &path) { - if (sys::path::is_absolute(path)) - return path; - SmallString<256> Ret; - sys::path::append(Ret, directory, path); - return NormalizePath(Ret.str()); -} - struct ProjectProcessor { ProjectConfig *config; std::unordered_set command_set; @@ -84,26 +74,26 @@ struct ProjectProcessor { const std::string base_name = sys::path::filename(entry.filename); // Expand %c %cpp %clang - std::vector args; - args.reserve(entry.args.size() + config->extra_flags.size() + 3); + std::vector args; + args.reserve(entry.args.size() + g_config->clang.extraArgs.size() + 1); const LanguageId lang = SourceFileLanguage(entry.filename); - for (const std::string &arg : entry.args) { - if (arg.compare(0, 3, "%c ") == 0) { + for (const char *arg : entry.args) { + if (strncmp(arg, "%c ", 3) == 0) { if (lang == LanguageId::C) - args.push_back(arg.substr(3)); - } else if (arg.compare(0, 5, "%cpp ") == 0) { + args.push_back(arg + 3); + } else if (strncmp(arg, "%cpp ", 5) == 0) { if (lang == LanguageId::Cpp) - args.push_back(arg.substr(5)); - } else if (arg == "%clang") { + args.push_back(arg + 5); + } else if (strcmp(arg, "%clang") == 0) { args.push_back(lang == LanguageId::Cpp ? "clang++" : "clang"); - } else { + } else if (!llvm::is_contained(g_config->clang.excludeArgs, arg)) { args.push_back(arg); } } if (args.empty()) return; - args.insert(args.end(), config->extra_flags.begin(), - config->extra_flags.end()); + for (const std::string &arg : g_config->clang.extraArgs) + args.push_back(Intern(arg)); size_t hash = std::hash{}(entry.directory); for (auto &arg : args) { @@ -116,21 +106,7 @@ struct ProjectProcessor { } hash_combine(hash, std::hash{}(arg)); } - for (size_t i = 1; i < args.size(); i++) - // This is most likely the file path we will be passing to clang. The - // path needs to be absolute, otherwise clang_codeCompleteAt is extremely - // slow. See - // https://github.com/cquery-project/cquery/commit/af63df09d57d765ce12d40007bf56302a0446678. - if (args[i][0] != '-' && EndsWith(args[i], base_name)) { - args[i] = ResolveIfRelative(entry.directory, args[i]); - continue; - } - - args.push_back("-resource-dir=" + g_config->clang.resourceDir); - args.push_back("-working-directory=" + entry.directory); - // There could be a clang version mismatch between what the project uses and - // what ccls uses. Make sure we do not emit warnings for mismatched options. - args.push_back("-Wno-unknown-warning-option"); + args.push_back(Intern("-working-directory=" + entry.directory)); if (!command_set.insert(hash).second) { entry.args = std::move(args); @@ -154,13 +130,9 @@ struct ProjectProcessor { } Driver.setCheckInputsExist(false); - std::vector cargs; - cargs.reserve(args.size() + 1); - for (auto &arg : args) - cargs.push_back(arg.c_str()); - cargs.push_back("-fsyntax-only"); + args.push_back("-fsyntax-only"); - std::unique_ptr C(Driver.BuildCompilation(cargs)); + std::unique_ptr C(Driver.BuildCompilation(args)); const driver::JobList &Jobs = C->getJobs(); if (Jobs.size() != 1) return; @@ -174,7 +146,8 @@ struct ProjectProcessor { HeaderSearchOptions &HeaderOpts = CI->getHeaderSearchOpts(); for (auto &E : HeaderOpts.UserEntries) { - std::string path = ResolveIfRelative(entry.directory, E.Path); + std::string path = + NormalizePath(ResolveIfRelative(entry.directory, E.Path)); switch (E.Group) { default: config->angle_dirs.insert(path); @@ -192,14 +165,17 @@ struct ProjectProcessor { } }; -std::vector +std::vector ReadCompilerArgumentsFromFile(const std::string &path) { auto MBOrErr = MemoryBuffer::getFile(path); if (!MBOrErr) return {}; - std::vector args; - for (line_iterator I(*MBOrErr.get(), true, '#'), E; I != E; ++I) - args.push_back(*I); + std::vector args; + for (line_iterator I(*MBOrErr.get(), true, '#'), E; I != E; ++I) { + std::string line = *I; + DoPathMapping(line); + args.push_back(Intern(line)); + } return args; } @@ -208,31 +184,33 @@ std::vector LoadFromDirectoryListing(ProjectConfig *config) { config->mode = ProjectMode::DotCcls; SmallString<256> Path; sys::path::append(Path, config->project_dir, ".ccls"); - LOG_IF_S(WARNING, !sys::fs::exists(Path) && config->extra_flags.empty()) + LOG_IF_S(WARNING, !sys::fs::exists(Path) && g_config->clang.extraArgs.empty()) << "ccls has no clang arguments. Use either " "compile_commands.json or .ccls, See ccls README for " "more information."; - std::unordered_map> folder_args; + std::unordered_map> folder_args; std::vector files; + const std::string &project_dir = config->project_dir; - GetFilesInFolder(config->project_dir, true /*recursive*/, + GetFilesInFolder(project_dir, true /*recursive*/, true /*add_folder_to_path*/, [&folder_args, &files](const std::string &path) { if (SourceFileLanguage(path) != LanguageId::Unknown) { files.push_back(path); } else if (sys::path::filename(path) == ".ccls") { - LOG_S(INFO) << "Using .ccls arguments from " << path; - folder_args.emplace(sys::path::parent_path(path), - ReadCompilerArgumentsFromFile(path)); + std::vector args = ReadCompilerArgumentsFromFile(path); + folder_args.emplace(sys::path::parent_path(path), args); + std::string l; + for (size_t i = 0; i < args.size(); i++) { + if (i) + l += ' '; + l += args[i]; + } + LOG_S(INFO) << "use " << path << ": " << l; } }); - const std::string &project_dir = config->project_dir; - const auto &project_dir_args = folder_args[project_dir]; - LOG_IF_S(INFO, !project_dir_args.empty()) - << "Using .ccls arguments " << StringJoin(project_dir_args); - auto GetCompilerArgumentForFile = [&project_dir, &folder_args](std::string cur) { while (!(cur = sys::path::parent_path(cur)).empty()) { @@ -256,7 +234,7 @@ std::vector LoadFromDirectoryListing(ProjectConfig *config) { e.args = GetCompilerArgumentForFile(file); if (e.args.empty()) e.args.push_back("%clang"); // Add a Dummy. - e.args.push_back(e.filename); + e.args.push_back(Intern(e.filename)); proc.Process(e); result.push_back(e); } @@ -329,9 +307,17 @@ LoadEntriesFromDirectory(ProjectConfig *project, ProjectProcessor proc(project); for (tooling::CompileCommand &Cmd : CDB->getAllCompileCommands()) { Project::Entry entry; - entry.directory = std::move(Cmd.Directory); - entry.filename = ResolveIfRelative(entry.directory, Cmd.Filename); - entry.args = std::move(Cmd.CommandLine); + entry.directory = NormalizePath(Cmd.Directory); + DoPathMapping(entry.directory); + entry.filename = + NormalizePath(ResolveIfRelative(entry.directory, Cmd.Filename)); + DoPathMapping(entry.filename); + std::vector args = std::move(Cmd.CommandLine); + entry.args.reserve(args.size()); + for (std::string &arg : args) { + DoPathMapping(arg); + entry.args.push_back(Intern(arg)); + } proc.Process(entry); if (Seen.insert(entry.filename).second) result.push_back(entry); @@ -356,12 +342,8 @@ int ComputeGuessScore(std::string_view a, std::string_view b) { } // namespace -bool Project::loaded = false; - void Project::Load(const std::string &root_directory) { - Project::loaded = false; ProjectConfig project; - project.extra_flags = g_config->clang.extraArgs; project.project_dir = root_directory; entries = LoadEntriesFromDirectory(&project, g_config->compilationDatabaseDirectory); @@ -379,40 +361,51 @@ void Project::Load(const std::string &root_directory) { EnsureEndsInSlash(path); LOG_S(INFO) << "angle_include_dir: " << path; } + + // Setup project entries. + std::lock_guard lock(mutex_); + path_to_entry_index.reserve(entries.size()); + for (size_t i = 0; i < entries.size(); ++i) { + entries[i].id = i; + path_to_entry_index[entries[i].filename] = i; + } } -void Project::SetFlagsForFile(const std::vector &flags, - const std::string &path) { +void Project::SetArgsForFile(const std::vector &args, + const std::string &path) { std::lock_guard lock(mutex_); - auto it = absolute_path_to_entry_index_.find(path); - if (it != absolute_path_to_entry_index_.end()) { + auto it = path_to_entry_index.find(path); + if (it != path_to_entry_index.end()) { // The entry already exists in the project, just set the flags. - this->entries[it->second].args = flags; + this->entries[it->second].args = args; } else { // Entry wasn't found, so we create a new one. Entry entry; entry.is_inferred = false; entry.filename = path; - entry.args = flags; + entry.args = args; this->entries.emplace_back(entry); } } -Project::Entry -Project::FindCompilationEntryForFile(const std::string &filename) { +Project::Entry Project::FindEntry(const std::string &path, + bool can_be_inferred) { { std::lock_guard lock(mutex_); - auto it = absolute_path_to_entry_index_.find(filename); - if (it != absolute_path_to_entry_index_.end()) - return entries[it->second]; + auto it = path_to_entry_index.find(path); + if (it != path_to_entry_index.end()) { + Project::Entry &entry = entries[it->second]; + if (can_be_inferred || entry.filename == path) + return entry; + } } // We couldn't find the file. Try to infer it. // TODO: Cache inferred file in a separate array (using a lock or similar) Entry *best_entry = nullptr; - int best_score = std::numeric_limits::min(); + int best_score = INT_MIN; for (Entry &entry : entries) { - int score = ComputeGuessScore(filename, entry.filename); + int score = ComputeGuessScore(path, entry.filename); if (score > best_score) { best_score = score; best_entry = &entry; @@ -421,10 +414,10 @@ Project::FindCompilationEntryForFile(const std::string &filename) { Project::Entry result; result.is_inferred = true; - result.filename = filename; + result.filename = path; if (!best_entry) { result.args.push_back("%clang"); - result.args.push_back(filename); + result.args.push_back(Intern(path)); } else { result.args = best_entry->args; @@ -432,11 +425,11 @@ Project::FindCompilationEntryForFile(const std::string &filename) { // that path to the new filename. std::string best_entry_base_name = sys::path::filename(best_entry->filename); - for (std::string &arg : result.args) { + for (const char *&arg : result.args) { try { if (arg == best_entry->filename || sys::path::filename(arg) == best_entry_base_name) - arg = filename; + arg = Intern(path); } catch (...) { } } @@ -445,27 +438,27 @@ Project::FindCompilationEntryForFile(const std::string &filename) { return result; } -void Project::ForAllFilteredFiles( - std::function action) { - GroupMatch matcher(g_config->index.whitelist, g_config->index.blacklist); +void Project::Index(WorkingFiles *wfiles, lsRequestId id) { + auto &gi = g_config->index; + GroupMatch match(gi.whitelist, gi.blacklist), + match_i(gi.initialWhitelist, gi.initialBlacklist); for (int i = 0; i < entries.size(); ++i) { const Project::Entry &entry = entries[i]; - std::string failure_reason; - if (matcher.IsMatch(entry.filename, &failure_reason)) - action(i, entries[i]); - else { - LOG_V(1) << "[" << i + 1 << "/" << entries.size() << "]: Failed " - << failure_reason << "; skipping " << entry.filename; + std::string reason; + if (match.IsMatch(entry.filename, &reason) && + match_i.IsMatch(entry.filename, &reason)) { + bool interactive = wfiles->GetFileByFilename(entry.filename) != nullptr; + pipeline::Index( + entry.filename, entry.args, + interactive ? IndexMode::Normal : IndexMode::NonInteractive, id); + } else { + LOG_V(1) << "[" << i << "/" << entries.size() << "]: " << reason + << "; skip " << entry.filename; } } -} -void Project::Index(WorkingFiles *wfiles, lsRequestId id) { - ForAllFilteredFiles([&](int i, const Project::Entry &entry) { - bool is_interactive = wfiles->GetFileByFilename(entry.filename) != nullptr; - pipeline::Index(entry.filename, entry.args, is_interactive, id); - }); + pipeline::loaded_ts = pipeline::tick; // Dummy request to indicate that project is loaded and // trigger refreshing semantic highlight for all working files. - pipeline::Index("", {}, false); + pipeline::Index("", {}, IndexMode::NonInteractive); } diff --git a/src/project.h b/src/project.h index 3baa545e..59a89855 100644 --- a/src/project.h +++ b/src/project.h @@ -30,7 +30,7 @@ struct Project { struct Entry { std::string directory; std::string filename; - std::vector args; + std::vector args; // If true, this entry is inferred and was not read from disk. bool is_inferred = false; int id = -1; @@ -43,7 +43,7 @@ struct Project { std::vector entries; std::mutex mutex_; - std::unordered_map absolute_path_to_entry_index_; + std::unordered_map path_to_entry_index; // Loads a project for the given |directory|. // @@ -59,19 +59,13 @@ struct Project { // Lookup the CompilationEntry for |filename|. If no entry was found this // will infer one based on existing project structure. - Entry FindCompilationEntryForFile(const std::string &filename); + Entry FindEntry(const std::string &path, bool can_be_inferred); // If the client has overridden the flags, or specified them for a file // that is not in the compilation_database.json make sure those changes // are permanent. - void SetFlagsForFile(const std::vector &flags, - const std::string &path); - - // Run |action| on every file in the project. - void - ForAllFilteredFiles(std::function action); + void SetArgsForFile(const std::vector &args, + const std::string &path); void Index(WorkingFiles *wfiles, lsRequestId id); - - static bool loaded; }; diff --git a/src/query.cc b/src/query.cc index 026aacf9..f052c42c 100644 --- a/src/query.cc +++ b/src/query.cc @@ -29,43 +29,17 @@ limitations under the License. namespace { -void AssignFileId(const Lid2file_id &, int file_id, SymbolRef &ref) { - if (ref.kind == SymbolKind::File) - ref.usr = file_id; -} - void AssignFileId(const Lid2file_id &lid2file_id, int file_id, Use &use) { - if (use.kind == SymbolKind::File) - use.usr = file_id; if (use.file_id == -1) use.file_id = file_id; else use.file_id = lid2file_id.find(use.file_id)->second; + if (use.kind == SymbolKind::File) + use.usr = use.file_id; } template -void AssignFileId(const Lid2file_id &, int file_id, T &) {} - -template -void AssignFileId(const Lid2file_id &lid2file_id, int file_id, Maybe &x) { - if (x) - AssignFileId(lid2file_id, file_id, *x); -} - -template -void AssignFileId(const Lid2file_id &lid2file_id, int file_id, - std::vector &xs) { - for (T &x : xs) - AssignFileId(lid2file_id, file_id, x); -} - -void AddRange(std::vector &into, const std::vector &from) { - into.reserve(into.size() + from.size()); - for (Use use : from) - into.push_back(use); -} - -void AddRange(std::vector &into, const std::vector &from) { +void AddRange(std::vector &into, const std::vector &from) { into.insert(into.end(), from.begin(), from.end()); } @@ -88,81 +62,8 @@ QueryFile::DefUpdate BuildFileDefUpdate(const IndexFile &indexed) { def.skipped_ranges = std::move(indexed.skipped_ranges); def.dependencies.reserve(indexed.dependencies.size()); for (auto &dep : indexed.dependencies) - def.dependencies.push_back(dep.first()); + def.dependencies.push_back(dep.first.val().data()); // llvm 8 -> data() def.language = indexed.language; - - auto add_all_symbols = [&](Use use, Usr usr, SymbolKind kind) { - def.all_symbols.push_back(SymbolRef{{use.range, usr, kind, use.role}}); - }; - auto add_outline = [&](Use use, Usr usr, SymbolKind kind) { - def.outline.push_back(SymbolRef{{use.range, usr, kind, use.role}}); - }; - - for (auto &it : indexed.usr2type) { - const IndexType &type = it.second; - if (type.def.spell) - add_all_symbols(*type.def.spell, type.usr, SymbolKind::Type); - if (type.def.extent) - add_outline(*type.def.extent, type.usr, SymbolKind::Type); - for (Use decl : type.declarations) { - add_all_symbols(decl, type.usr, SymbolKind::Type); - // Constructor positions have references to the class, - // which we do not want to show in textDocument/documentSymbol - if (!(decl.role & Role::Reference)) - add_outline(decl, type.usr, SymbolKind::Type); - } - for (Use use : type.uses) - if (use.file_id == -1) - add_all_symbols(use, type.usr, SymbolKind::Type); - } - for (auto &it : indexed.usr2func) { - const IndexFunc &func = it.second; - if (func.def.spell) - add_all_symbols(*func.def.spell, func.usr, SymbolKind::Func); - if (func.def.extent) - add_outline(*func.def.extent, func.usr, SymbolKind::Func); - for (Use use : func.declarations) { - add_all_symbols(use, func.usr, SymbolKind::Func); - add_outline(use, func.usr, SymbolKind::Func); - } - for (Use use : func.uses) - if (use.file_id == -1) { - // Make ranges of implicit function calls larger (spanning one more - // column to the left/right). This is hacky but useful. e.g. - // textDocument/definition on the space/semicolon in `A a;` or `return - // 42;` will take you to the constructor. - if (use.role & Role::Implicit) { - if (use.range.start.column > 0) - use.range.start.column--; - use.range.end.column++; - } - add_all_symbols(use, func.usr, SymbolKind::Func); - } - } - for (auto &it : indexed.usr2var) { - const IndexVar &var = it.second; - if (var.def.spell) - add_all_symbols(*var.def.spell, var.usr, SymbolKind::Var); - if (var.def.extent) - add_outline(*var.def.extent, var.usr, SymbolKind::Var); - for (Use decl : var.declarations) { - add_all_symbols(decl, var.usr, SymbolKind::Var); - add_outline(decl, var.usr, SymbolKind::Var); - } - for (Use use : var.uses) - if (use.file_id == -1) - add_all_symbols(use, var.usr, SymbolKind::Var); - } - - std::sort(def.outline.begin(), def.outline.end(), - [](const SymbolRef &a, const SymbolRef &b) { - return a.range.start < b.range.start; - }); - std::sort(def.all_symbols.begin(), def.all_symbols.end(), - [](const SymbolRef &a, const SymbolRef &b) { - return a.range.start < b.range.start; - }); - return {std::move(def), std::move(indexed.file_contents)}; } @@ -194,7 +95,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { for (auto &it : previous->usr2func) { auto &func = it.second; if (func.def.detailed_name[0]) - r.funcs_removed.push_back(func.usr); + r.funcs_removed.emplace_back(func.usr, func.def); r.funcs_declarations[func.usr].first = std::move(func.declarations); r.funcs_uses[func.usr].first = std::move(func.uses); r.funcs_derived[func.usr].first = std::move(func.derived); @@ -212,7 +113,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { for (auto &it : previous->usr2type) { auto &type = it.second; if (type.def.detailed_name[0]) - r.types_removed.push_back(type.usr); + r.types_removed.emplace_back(type.usr, type.def); r.types_declarations[type.usr].first = std::move(type.declarations); r.types_uses[type.usr].first = std::move(type.uses); r.types_derived[type.usr].first = std::move(type.derived); @@ -232,7 +133,7 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { for (auto &it : previous->usr2var) { auto &var = it.second; if (var.def.detailed_name[0]) - r.vars_removed.push_back(var.usr); + r.vars_removed.emplace_back(var.usr, var.def); r.vars_declarations[var.usr].first = std::move(var.declarations); r.vars_uses[var.usr].first = std::move(var.uses); } @@ -247,11 +148,23 @@ IndexUpdate IndexUpdate::CreateDelta(IndexFile *previous, IndexFile *current) { return r; } +void DB::clear() { + files.clear(); + name2file_id.clear(); + func_usr.clear(); + type_usr.clear(); + var_usr.clear(); + funcs.clear(); + types.clear(); + vars.clear(); +} + +template void DB::RemoveUsrs(SymbolKind kind, int file_id, - const std::vector &to_remove) { + const std::vector> &to_remove) { switch (kind) { case SymbolKind::Func: { - for (Usr usr : to_remove) { + for (auto &[usr, _] : to_remove) { // FIXME if (!HasFunc(usr)) continue; @@ -265,7 +178,7 @@ void DB::RemoveUsrs(SymbolKind kind, int file_id, break; } case SymbolKind::Type: { - for (Usr usr : to_remove) { + for (auto &[usr, _] : to_remove) { // FIXME if (!HasType(usr)) continue; @@ -279,7 +192,7 @@ void DB::RemoveUsrs(SymbolKind kind, int file_id, break; } case SymbolKind::Var: { - for (Usr usr : to_remove) { + for (auto &[usr, _] : to_remove) { // FIXME if (!HasVar(usr)) continue; @@ -304,46 +217,81 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { if (R.second) \ C##s.emplace_back().usr = it.first; \ auto &entity = C##s[R.first->second]; \ - AssignFileId(prev_lid2file_id, u->file_id, it.second.first); \ RemoveRange(entity.F, it.second.first); \ - AssignFileId(lid2file_id, u->file_id, it.second.second); \ AddRange(entity.F, it.second.second); \ } std::unordered_map prev_lid2file_id, lid2file_id; for (auto &[lid, path] : u->prev_lid2path) prev_lid2file_id[lid] = GetFileId(path); - for (auto &[lid, path] : u->lid2path) - lid2file_id[lid] = GetFileId(path); + for (auto &[lid, path] : u->lid2path) { + int file_id = GetFileId(path); + lid2file_id[lid] = file_id; + if (!files[file_id].def) { + files[file_id].def = QueryFile::Def(); + files[file_id].def->path = path; + } + } - auto UpdateUses = [&](Usr usr, SymbolKind kind, - llvm::DenseMap &entity_usr, - auto &entities, auto &p) { - auto R = entity_usr.try_emplace({usr}, entity_usr.size()); - if (R.second) - vars.emplace_back().usr = usr; - auto &entity = entities[R.first->second]; - for (Use &use : p.first) { - if (use.file_id == -1) - use.file_id = u->file_id; - else { - use.file_id = prev_lid2file_id.find(use.file_id)->second; - files[use.file_id] - .symbol2refcnt[SymbolRef{{use.range, usr, kind, use.role}}]--; - } + // References (Use &use) in this function are important to update file_id. + auto Ref = [&](std::unordered_map &lid2fid, Usr usr, + SymbolKind kind, Use &use, int delta, int k = 1) { + use.file_id = + use.file_id == -1 ? u->file_id : lid2fid.find(use.file_id)->second; + SymbolRef sym{{use.range, usr, kind, use.role}}; + if (k & 1) { + int &v = files[use.file_id].symbol2refcnt[sym]; + v += delta; + assert(v >= 0); + if (!v) + files[use.file_id].symbol2refcnt.erase(sym); } - RemoveRange(entity.uses, p.first); - for (Use &use : p.second) { - if (use.file_id == -1) - use.file_id = u->file_id; - else { - use.file_id = lid2file_id.find(use.file_id)->second; - files[use.file_id] - .symbol2refcnt[SymbolRef{{use.range, usr, kind, use.role}}]++; - } + if (k & 2) { + int &v = files[use.file_id].outline2refcnt[sym]; + v += delta; + assert(v >= 0); + if (!v) + files[use.file_id].outline2refcnt.erase(sym); } - AddRange(entity.uses, p.second); }; + auto RefDecl = [&](std::unordered_map &lid2fid, Usr usr, + SymbolKind kind, DeclRef &dr, int delta) { + Ref(lid2fid, usr, kind, dr, delta, 1); + files[dr.file_id] + .outline2refcnt[SymbolRef{{dr.extent, usr, kind, dr.role}}] += delta; + }; + + auto UpdateUses = + [&](Usr usr, SymbolKind kind, + llvm::DenseMap &entity_usr, + auto &entities, auto &p, bool hint_implicit) { + auto R = entity_usr.try_emplace(usr, entity_usr.size()); + if (R.second) + vars.emplace_back().usr = usr; + auto &entity = entities[R.first->second]; + for (Use &use : p.first) { + if (hint_implicit && use.role & Role::Implicit) { + // Make ranges of implicit function calls larger (spanning one more + // column to the left/right). This is hacky but useful. e.g. + // textDocument/definition on the space/semicolon in `A a;` or ` + // 42;` will take you to the constructor. + if (use.range.start.column > 0) + use.range.start.column--; + use.range.end.column++; + } + Ref(prev_lid2file_id, usr, kind, use, -1); + } + RemoveRange(entity.uses, p.first); + for (Use &use : p.second) { + if (hint_implicit && use.role & Role::Implicit) { + if (use.range.start.column > 0) + use.range.start.column--; + use.range.end.column++; + } + Ref(lid2file_id, usr, kind, use, 1); + } + AddRange(entity.uses, p.second); + }; if (u->files_removed) files[name2file_id[LowerPathIfInsensitive(*u->files_removed)]].def = @@ -359,36 +307,72 @@ void DB::ApplyIndexUpdate(IndexUpdate *u) { funcs.reserve(t); func_usr.reserve(t); } + for (auto &[usr, def] : u->funcs_removed) { + if (def.spell) + Ref(prev_lid2file_id, usr, SymbolKind::Func, *def.spell, -1); + if (def.extent) + Ref(prev_lid2file_id, usr, SymbolKind::Func, *def.extent, -1, 2); + } RemoveUsrs(SymbolKind::Func, u->file_id, u->funcs_removed); Update(lid2file_id, u->file_id, std::move(u->funcs_def_update)); + for (auto &[usr, del_add]: u->funcs_declarations) { + for (DeclRef &dr : del_add.first) + RefDecl(prev_lid2file_id, usr, SymbolKind::Func, dr, -1); + for (DeclRef &dr : del_add.second) + RefDecl(lid2file_id, usr, SymbolKind::Func, dr, 1); + } REMOVE_ADD(func, declarations); REMOVE_ADD(func, derived); for (auto &[usr, p] : u->funcs_uses) - UpdateUses(usr, SymbolKind::Func, func_usr, funcs, p); + UpdateUses(usr, SymbolKind::Func, func_usr, funcs, p, true); if ((t = types.size() + u->types_hint) > types.capacity()) { t = size_t(t * grow); types.reserve(t); type_usr.reserve(t); } + for (auto &[usr, def] : u->types_removed) { + if (def.spell) + Ref(prev_lid2file_id, usr, SymbolKind::Type, *def.spell, -1); + if (def.extent) + Ref(prev_lid2file_id, usr, SymbolKind::Type, *def.extent, -1, 2); + } RemoveUsrs(SymbolKind::Type, u->file_id, u->types_removed); Update(lid2file_id, u->file_id, std::move(u->types_def_update)); + for (auto &[usr, del_add]: u->types_declarations) { + for (DeclRef &dr : del_add.first) + RefDecl(prev_lid2file_id, usr, SymbolKind::Type, dr, -1); + for (DeclRef &dr : del_add.second) + RefDecl(lid2file_id, usr, SymbolKind::Type, dr, 1); + } REMOVE_ADD(type, declarations); REMOVE_ADD(type, derived); REMOVE_ADD(type, instances); for (auto &[usr, p] : u->types_uses) - UpdateUses(usr, SymbolKind::Type, type_usr, types, p); + UpdateUses(usr, SymbolKind::Type, type_usr, types, p, false); if ((t = vars.size() + u->vars_hint) > vars.capacity()) { t = size_t(t * grow); vars.reserve(t); var_usr.reserve(t); } + for (auto &[usr, def] : u->vars_removed) { + if (def.spell) + Ref(prev_lid2file_id, usr, SymbolKind::Var, *def.spell, -1); + if (def.extent) + Ref(prev_lid2file_id, usr, SymbolKind::Var, *def.extent, -1, 2); + } RemoveUsrs(SymbolKind::Var, u->file_id, u->vars_removed); Update(lid2file_id, u->file_id, std::move(u->vars_def_update)); + for (auto &[usr, del_add]: u->vars_declarations) { + for (DeclRef &dr : del_add.first) + RefDecl(prev_lid2file_id, usr, SymbolKind::Var, dr, -1); + for (DeclRef &dr : del_add.second) + RefDecl(lid2file_id, usr, SymbolKind::Var, dr, 1); + } REMOVE_ADD(var, declarations); for (auto &[usr, p] : u->vars_uses) - UpdateUses(usr, SymbolKind::Var, var_usr, vars, p); + UpdateUses(usr, SymbolKind::Var, var_usr, vars, p, false); #undef REMOVE_ADD } @@ -414,9 +398,17 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, auto &def = u.second; assert(def.detailed_name[0]); u.second.file_id = file_id; - AssignFileId(lid2file_id, file_id, def.spell); - AssignFileId(lid2file_id, file_id, def.extent); - AssignFileId(lid2file_id, file_id, def.callees); + if (def.spell) { + AssignFileId(lid2file_id, file_id, *def.spell); + files[def.spell->file_id].symbol2refcnt[{ + {def.spell->range, u.first, SymbolKind::Func, def.spell->role}}]++; + } + if (def.extent) { + AssignFileId(lid2file_id, file_id, *def.extent); + files[def.extent->file_id].outline2refcnt[{ + {def.extent->range, u.first, SymbolKind::Func, def.extent->role}}]++; + } + auto R = func_usr.try_emplace({u.first}, func_usr.size()); if (R.second) funcs.emplace_back(); @@ -433,8 +425,16 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, auto &def = u.second; assert(def.detailed_name[0]); u.second.file_id = file_id; - AssignFileId(lid2file_id, file_id, def.spell); - AssignFileId(lid2file_id, file_id, def.extent); + if (def.spell) { + AssignFileId(lid2file_id, file_id, *def.spell); + files[def.spell->file_id].symbol2refcnt[{ + {def.spell->range, u.first, SymbolKind::Type, def.spell->role}}]++; + } + if (def.extent) { + AssignFileId(lid2file_id, file_id, *def.extent); + files[def.extent->file_id].outline2refcnt[{ + {def.extent->range, u.first, SymbolKind::Type, def.extent->role}}]++; + } auto R = type_usr.try_emplace({u.first}, type_usr.size()); if (R.second) types.emplace_back(); @@ -451,8 +451,16 @@ void DB::Update(const Lid2file_id &lid2file_id, int file_id, auto &def = u.second; assert(def.detailed_name[0]); u.second.file_id = file_id; - AssignFileId(lid2file_id, file_id, def.spell); - AssignFileId(lid2file_id, file_id, def.extent); + if (def.spell) { + AssignFileId(lid2file_id, file_id, *def.spell); + files[def.spell->file_id].symbol2refcnt[{ + {def.spell->range, u.first, SymbolKind::Var, def.spell->role}}]++; + } + if (def.extent) { + AssignFileId(lid2file_id, file_id, *def.extent); + files[def.extent->file_id].outline2refcnt[{ + {def.extent->range, u.first, SymbolKind::Var, def.extent->role}}]++; + } auto R = var_usr.try_emplace({u.first}, var_usr.size()); if (R.second) vars.emplace_back(); diff --git a/src/query.h b/src/query.h index 1513da0f..3cc50fd6 100644 --- a/src/query.h +++ b/src/query.h @@ -21,28 +21,40 @@ limitations under the License. #include #include +namespace llvm { +template <> struct DenseMapInfo { + static inline SymbolRef getEmptyKey() { return {}; } + static inline SymbolRef getTombstoneKey() { + SymbolRef ret{}; + ret.usr = -1; + return ret; + } + static unsigned getHashValue(SymbolRef sym) { + return std::hash()(sym); + } + static bool isEqual(SymbolRef l, SymbolRef r) { return l == r; } +}; +} + struct QueryFile { struct Def { std::string path; - std::vector args; + std::vector args; LanguageId language; // Includes in the file. std::vector includes; - // Outline of the file (ie, for code lens). - std::vector outline; - // Every symbol found in the file (ie, for goto definition) - std::vector all_symbols; // Parts of the file which are disabled. std::vector skipped_ranges; - // Used by |$ccls/freshenIndex|. - std::vector dependencies; + // Used by |$ccls/reload|. + std::vector dependencies; }; using DefUpdate = std::pair; int id = -1; std::optional def; - std::unordered_map symbol2refcnt; + llvm::DenseMap symbol2refcnt; + llvm::DenseMap outline2refcnt; }; template struct QueryEntity { @@ -61,6 +73,9 @@ template struct QueryEntity { } }; +using DeclRefUpdate = + std::unordered_map, std::vector>>; using UseUpdate = std::unordered_map, std::vector>>; using UsrUpdate = @@ -69,7 +84,7 @@ using UsrUpdate = struct QueryFunc : QueryEntity { Usr usr; llvm::SmallVector def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; }; @@ -77,7 +92,7 @@ struct QueryFunc : QueryEntity { struct QueryType : QueryEntity { Usr usr; llvm::SmallVector def; - std::vector declarations; + std::vector declarations; std::vector uses; std::vector derived; std::vector instances; @@ -86,7 +101,7 @@ struct QueryType : QueryEntity { struct QueryVar : QueryEntity { Usr usr; llvm::SmallVector def; - std::vector declarations; + std::vector declarations; std::vector uses; }; @@ -109,37 +124,34 @@ struct IndexUpdate { // Function updates. int funcs_hint; - std::vector funcs_removed; + std::vector> funcs_removed; std::vector> funcs_def_update; - UseUpdate funcs_declarations; + DeclRefUpdate funcs_declarations; UseUpdate funcs_uses; UsrUpdate funcs_derived; // Type updates. int types_hint; - std::vector types_removed; + std::vector> types_removed; std::vector> types_def_update; - UseUpdate types_declarations; + DeclRefUpdate types_declarations; UseUpdate types_uses; UsrUpdate types_derived; UsrUpdate types_instances; // Variable updates. int vars_hint; - std::vector vars_removed; + std::vector> vars_removed; std::vector> vars_def_update; - UseUpdate vars_declarations; + DeclRefUpdate vars_declarations; UseUpdate vars_uses; }; -struct WrappedUsr { - Usr usr; -}; -template <> struct llvm::DenseMapInfo { - static inline WrappedUsr getEmptyKey() { return {0}; } - static inline WrappedUsr getTombstoneKey() { return {~0ULL}; } - static unsigned getHashValue(WrappedUsr w) { return w.usr; } - static bool isEqual(WrappedUsr l, WrappedUsr r) { return l.usr == r.usr; } +struct DenseMapInfoForUsr { + static inline Usr getEmptyKey() { return 0; } + static inline Usr getTombstoneKey() { return ~0ULL; } + static unsigned getHashValue(Usr w) { return w; } + static bool isEqual(Usr l, Usr r) { return l == r; } }; using Lid2file_id = std::unordered_map; @@ -149,13 +161,16 @@ using Lid2file_id = std::unordered_map; struct DB { std::vector files; llvm::StringMap name2file_id; - llvm::DenseMap func_usr, type_usr, var_usr; + llvm::DenseMap func_usr, type_usr, var_usr; std::vector funcs; std::vector types; std::vector vars; + void clear(); + + template void RemoveUsrs(SymbolKind kind, int file_id, - const std::vector &to_remove); + const std::vector> &to_remove); // Insert the contents of |update| into |db|. void ApplyIndexUpdate(IndexUpdate *update); int GetFileId(const std::string &path); @@ -168,13 +183,13 @@ struct DB { std::vector> &&us); std::string_view GetSymbolName(SymbolIdx sym, bool qualified); - bool HasFunc(Usr usr) const { return func_usr.count({usr}); } - bool HasType(Usr usr) const { return type_usr.count({usr}); } - bool HasVar(Usr usr) const { return var_usr.count({usr}); } + bool HasFunc(Usr usr) const { return func_usr.count(usr); } + bool HasType(Usr usr) const { return type_usr.count(usr); } + bool HasVar(Usr usr) const { return var_usr.count(usr); } - QueryFunc &Func(Usr usr) { return funcs[func_usr[{usr}]]; } - QueryType &Type(Usr usr) { return types[type_usr[{usr}]]; } - QueryVar &Var(Usr usr) { return vars[var_usr[{usr}]]; } + QueryFunc &Func(Usr usr) { return funcs[func_usr[usr]]; } + QueryType &Type(Usr usr) { return types[type_usr[usr]]; } + QueryVar &Var(Usr usr) { return vars[var_usr[usr]]; } QueryFile &GetFile(SymbolIdx ref) { return files[ref.usr]; } QueryFunc &GetFunc(SymbolIdx ref) { return Func(ref.usr); } diff --git a/src/query_utils.cc b/src/query_utils.cc index 23349d7c..27ce5f71 100644 --- a/src/query_utils.cc +++ b/src/query_utils.cc @@ -30,9 +30,9 @@ int ComputeRangeSize(const Range &range) { } template -std::vector GetDeclarations(llvm::DenseMap &entity_usr, - std::vector &entities, - const std::vector &usrs) { +std::vector +GetDeclarations(llvm::DenseMap &entity_usr, + std::vector &entities, const std::vector &usrs) { std::vector ret; ret.reserve(usrs.size()); for (Usr usr : usrs) { @@ -105,16 +105,24 @@ std::vector GetVarDeclarations(DB *db, const std::vector &usrs, } std::vector GetNonDefDeclarations(DB *db, SymbolIdx sym) { + std::vector ret; switch (sym.kind) { case SymbolKind::Func: - return db->GetFunc(sym).declarations; + for (auto &d : db->GetFunc(sym).declarations) + ret.push_back(d); + break; case SymbolKind::Type: - return db->GetType(sym).declarations; + for (auto &d : db->GetType(sym).declarations) + ret.push_back(d); + break; case SymbolKind::Var: - return db->GetVar(sym).declarations; + for (auto &d : db->GetVar(sym).declarations) + ret.push_back(d); + break; default: - return {}; + break; } + return ret; } std::vector GetUsesForAllBases(DB *db, QueryFunc &root) { @@ -159,29 +167,16 @@ std::vector GetUsesForAllDerived(DB *db, QueryFunc &root) { return ret; } -std::optional GetLsPosition(WorkingFile *working_file, - const Position &position) { - if (!working_file) - return lsPosition{position.line, position.column}; - - int column = position.column; - if (std::optional start = - working_file->GetBufferPosFromIndexPos(position.line, &column, false)) - return lsPosition{*start, column}; - return std::nullopt; -} - -std::optional GetLsRange(WorkingFile *working_file, +std::optional GetLsRange(WorkingFile *wfile, const Range &location) { - if (!working_file) { + if (!wfile || wfile->index_lines.empty()) return lsRange{lsPosition{location.start.line, location.start.column}, lsPosition{location.end.line, location.end.column}}; - } int start_column = location.start.column, end_column = location.end.column; - std::optional start = working_file->GetBufferPosFromIndexPos( + std::optional start = wfile->GetBufferPosFromIndexPos( location.start.line, &start_column, false); - std::optional end = working_file->GetBufferPosFromIndexPos( + std::optional end = wfile->GetBufferPosFromIndexPos( location.end.line, &end_column, true); if (!start || !end) return std::nullopt; @@ -279,11 +274,8 @@ lsSymbolKind GetSymbolKind(DB *db, SymbolIdx sym) { return ret; } -// Returns a symbol. The symbol will have *NOT* have a location assigned. -std::optional GetSymbolInfo(DB *db, - WorkingFiles *working_files, - SymbolIdx sym, - bool detailed_name) { +std::optional GetSymbolInfo(DB *db, SymbolIdx sym, + bool detailed) { switch (sym.kind) { case SymbolKind::Invalid: break; @@ -300,12 +292,11 @@ std::optional GetSymbolInfo(DB *db, default: { lsSymbolInformation info; EachEntityDef(db, sym, [&](const auto &def) { - if (detailed_name) + if (detailed) info.name = def.detailed_name; else info.name = def.Name(true); info.kind = def.kind; - info.containerName = def.detailed_name; return false; }); return info; @@ -315,12 +306,14 @@ std::optional GetSymbolInfo(DB *db, return std::nullopt; } -std::vector FindSymbolsAtLocation(WorkingFile *working_file, +std::vector FindSymbolsAtLocation(WorkingFile *wfile, QueryFile *file, - lsPosition &ls_pos) { + lsPosition &ls_pos, + bool smallest) { std::vector symbols; - if (working_file) { - if (auto line = working_file->GetIndexPosFromBufferPos( + // If multiVersion > 0, index may not exist and thus index_lines is empty. + if (wfile && wfile->index_lines.size()) { + if (auto line = wfile->GetIndexPosFromBufferPos( ls_pos.line, &ls_pos.character, false)) { ls_pos.line = *line; } else { @@ -329,9 +322,6 @@ std::vector FindSymbolsAtLocation(WorkingFile *working_file, } } - for (SymbolRef sym : file->def->all_symbols) - if (sym.range.Contains(ls_pos.line, ls_pos.character)) - symbols.push_back(sym); for (auto [sym, refcnt] : file->symbol2refcnt) if (refcnt > 0 && sym.range.Contains(ls_pos.line, ls_pos.character)) symbols.push_back(sym); @@ -364,6 +354,14 @@ std::vector FindSymbolsAtLocation(WorkingFile *working_file, return t > 0; return a.usr < b.usr; }); + if (symbols.size() && smallest) { + SymbolRef sym = symbols[0]; + for (size_t i = 1; i < symbols.size(); i++) + if (!(sym.range == symbols[i].range && sym.kind == symbols[i].kind)) { + symbols.resize(i); + break; + } + } return symbols; } diff --git a/src/query_utils.h b/src/query_utils.h index 262fbdfa..642a6ba1 100644 --- a/src/query_utils.h +++ b/src/query_utils.h @@ -34,8 +34,6 @@ std::vector GetNonDefDeclarations(DB *db, SymbolIdx sym); std::vector GetUsesForAllBases(DB *db, QueryFunc &root); std::vector GetUsesForAllDerived(DB *db, QueryFunc &root); -std::optional GetLsPosition(WorkingFile *working_file, - const Position &position); std::optional GetLsRange(WorkingFile *working_file, const Range &location); lsDocumentUri GetLsDocumentUri(DB *db, int file_id, std::string *path); @@ -47,15 +45,14 @@ std::optional GetLsLocationEx(DB *db, WorkingFiles *working_files, Use use, bool container); std::vector GetLsLocationExs(DB *db, WorkingFiles *working_files, const std::vector &refs); -// Returns a symbol. The symbol will have *NOT* have a location assigned. -std::optional GetSymbolInfo(DB *db, - WorkingFiles *working_files, - SymbolIdx sym, - bool detailed_name); +// Returns a symbol. The symbol will *NOT* have a location assigned. +std::optional GetSymbolInfo(DB *db, SymbolIdx sym, + bool detailed); std::vector FindSymbolsAtLocation(WorkingFile *working_file, QueryFile *file, - lsPosition &ls_pos); + lsPosition &ls_pos, + bool smallest = false); template void WithEntity(DB *db, SymbolIdx sym, Fn &&fn) { switch (sym.kind) { @@ -107,21 +104,3 @@ void EachDefinedFunc(DB *db, const std::vector &usrs, Fn &&fn) { fn(obj); } } - -template -void EachDefinedType(DB *db, const std::vector &usrs, Fn &&fn) { - for (Usr usr : usrs) { - auto &obj = db->Type(usr); - if (!obj.def.empty()) - fn(obj); - } -} - -template -void EachDefinedVar(DB *db, const std::vector &usrs, Fn &&fn) { - for (Usr usr : usrs) { - auto &obj = db->Var(usr); - if (!obj.def.empty()) - fn(obj); - } -} diff --git a/src/serializer.cc b/src/serializer.cc index e99b3815..68c80493 100644 --- a/src/serializer.cc +++ b/src/serializer.cc @@ -27,6 +27,7 @@ limitations under the License. #include #include +using namespace ccls; using namespace llvm; bool gTestOutputMode = false; @@ -127,7 +128,7 @@ void Reflect(Writer &visitor, std::string_view &data) { void Reflect(Reader &vis, const char *&v) { const char *str = vis.GetString(); - v = ccls::Intern(str); + v = Intern(str); } void Reflect(Writer &vis, const char *&v) { vis.String(v); } @@ -159,26 +160,38 @@ void Reflect(Writer &visitor, std::unordered_map &map) { visitor.EndArray(); } -// Used by IndexFile::dependencies. Timestamps are emitted for Binary. -void Reflect(Reader &visitor, StringMap &map) { - visitor.IterArray([&](Reader &entry) { - std::string name; - Reflect(entry, name); - if (visitor.Format() == SerializeFormat::Binary) - Reflect(entry, map[name]); - else - map[name] = 0; - }); -} -void Reflect(Writer &visitor, StringMap &map) { - visitor.StartArray(map.size()); - for (auto &it : map) { - std::string key = it.first(); - Reflect(visitor, key); - if (visitor.Format() == SerializeFormat::Binary) - Reflect(visitor, it.second); +// Used by IndexFile::dependencies. +void Reflect(Reader &vis, DenseMap &v) { + std::string name; + if (vis.Format() == SerializeFormat::Json) { + auto &vis1 = static_cast(vis); + for (auto it = vis1.m().MemberBegin(); it != vis1.m().MemberEnd(); ++it) + v[InternH(it->name.GetString())] = it->value.GetInt64(); + } else { + vis.IterArray([&](Reader &entry) { + Reflect(entry, name); + Reflect(entry, v[InternH(name)]); + }); + } +} +void Reflect(Writer &vis, DenseMap &v) { + if (vis.Format() == SerializeFormat::Json) { + auto &vis1 = static_cast(vis); + vis.StartObject(); + for (auto &it : v) { + vis1.m().Key(it.first.val().data()); // llvm 8 -> data() + vis1.m().Int64(it.second); + } + vis.EndObject(); + } else { + vis.StartArray(v.size()); + for (auto &it : v) { + std::string key = it.first.val().str(); + Reflect(vis, key); + Reflect(vis, it.second); + } + vis.EndArray(); } - visitor.EndArray(); } // TODO: Move this to indexer.cc @@ -309,7 +322,7 @@ bool ReflectMemberStart(Writer &visitor, IndexFile &value) { template void Reflect(TVisitor &visitor, IndexFile &value) { REFLECT_MEMBER_START(); if (!gTestOutputMode) { - REFLECT_MEMBER(last_write_time); + REFLECT_MEMBER(mtime); REFLECT_MEMBER(language); REFLECT_MEMBER(lid2path); REFLECT_MEMBER(import_file); @@ -324,9 +337,9 @@ template void Reflect(TVisitor &visitor, IndexFile &value) { REFLECT_MEMBER_END(); } -void Reflect(Reader &visitor, SerializeFormat &value) { - std::string fmt = visitor.GetString(); - value = fmt[0] == 'b' ? SerializeFormat::Binary : SerializeFormat::Json; +void Reflect(Reader &vis, SerializeFormat &v) { + v = vis.GetString()[0] == 'j' ? SerializeFormat::Json + : SerializeFormat::Binary; } void Reflect(Writer &visitor, SerializeFormat &value) { @@ -342,18 +355,26 @@ void Reflect(Writer &visitor, SerializeFormat &value) { namespace ccls { static BumpPtrAllocator Alloc; -static DenseSet Strings; +static DenseSet Strings; static std::mutex AllocMutex; -const char *Intern(const std::string &str) { - if (str.empty()) - return ""; - StringRef Str(str.data(), str.size() + 1); +CachedHashStringRef InternH(StringRef S) { + if (S.empty()) + S = ""; + CachedHashString HS(S); std::lock_guard lock(AllocMutex); - auto R = Strings.insert(Str); - if (R.second) - *R.first = Str.copy(Alloc); - return R.first->data(); + auto R = Strings.insert(HS); + if (R.second) { + char *P = Alloc.Allocate(S.size() + 1); + memcpy(P, S.data(), S.size()); + P[S.size()] = '\0'; + *R.first = CachedHashStringRef(StringRef(P, S.size()), HS.hash()); + } + return *R.first; +} + +const char *Intern(StringRef S) { + return InternH(S).val().data(); } std::string Serialize(SerializeFormat format, IndexFile &file) { @@ -448,6 +469,30 @@ Deserialize(SerializeFormat format, const std::string &path, // Restore non-serialized state. file->path = path; + if (g_config->clang.pathMappings.size()) { + DoPathMapping(file->import_file); + std::vector args; + for (const char *arg : file->args) { + std::string s(arg); + DoPathMapping(s); + args.push_back(Intern(s)); + } + file->args = std::move(args); + for (auto &[_, path] : file->lid2path) + DoPathMapping(path); + for (auto &include : file->includes) { + std::string p(include.resolved_path); + DoPathMapping(p); + include.resolved_path = Intern(p); + } + decltype(file->dependencies) dependencies; + for (auto &it : file->dependencies) { + std::string path = it.first.val().str(); + DoPathMapping(path); + dependencies[InternH(path)] = it.second; + } + file->dependencies = std::move(dependencies); + } return file; } } // namespace ccls diff --git a/src/serializer.h b/src/serializer.h index 7e248715..5e05a475 100644 --- a/src/serializer.h +++ b/src/serializer.h @@ -30,6 +30,11 @@ limitations under the License. #include #include +namespace llvm { +class CachedHashStringRef; +class StringRef; +} + enum class SerializeFormat { Binary, Json }; struct JsonNull {}; @@ -320,7 +325,8 @@ template void ReflectMember(Writer &vis, const char *name, T &v) { // API namespace ccls { -const char *Intern(const std::string &str); +const char *Intern(llvm::StringRef str); +llvm::CachedHashStringRef InternH(llvm::StringRef str); std::string Serialize(SerializeFormat format, IndexFile &file); std::unique_ptr Deserialize(SerializeFormat format, const std::string &path, diff --git a/src/serializers/binary.h b/src/serializers/binary.h index 1b86fac8..a1c9266f 100644 --- a/src/serializers/binary.h +++ b/src/serializers/binary.h @@ -17,13 +17,14 @@ limitations under the License. #include "serializer.h" -#include +#include class BinaryReader : public Reader { const char *p_; template T Get() { - auto ret = *reinterpret_cast(p_); + T ret; + memcpy(&ret, p_, sizeof(T)); p_ += sizeof(T); return ret; } @@ -89,7 +90,7 @@ class BinaryWriter : public Writer { template void Pack(T x) { auto i = buf_.size(); buf_.resize(i + sizeof(x)); - *reinterpret_cast(buf_.data() + i) = x; + memcpy(buf_.data() + i, &x, sizeof(x)); } void VarUInt(uint64_t n) { diff --git a/src/serializers/json.h b/src/serializers/json.h index 131556c2..fb3751bc 100644 --- a/src/serializers/json.h +++ b/src/serializers/json.h @@ -27,6 +27,7 @@ class JsonReader : public Reader { public: JsonReader(rapidjson::GenericValue> *m) : m_(m) {} SerializeFormat Format() const override { return SerializeFormat::Json; } + rapidjson::GenericValue> &m() { return *m_; } bool IsBool() override { return m_->IsBool(); } bool IsNull() override { return m_->IsNull(); } @@ -95,6 +96,7 @@ class JsonWriter : public Writer { public: JsonWriter(rapidjson::Writer *m) : m_(m) {} SerializeFormat Format() const override { return SerializeFormat::Json; } + rapidjson::Writer &m() { return *m_; } void Null() override { m_->Null(); } void Bool(bool x) override { m_->Bool(x); } diff --git a/src/symbol.h b/src/symbol.h index a4f3c05d..beec82b8 100644 --- a/src/symbol.h +++ b/src/symbol.h @@ -46,36 +46,10 @@ inline Role operator|(Role lhs, Role rhs) { return Role(uint16_t(lhs) | uint16_t(rhs)); } -// A document highlight kind. -enum class lsDocumentHighlightKind { - // A textual occurrence. - Text = 1, - // Read-access of a symbol, like reading a variable. - Read = 2, - // Write-access of a symbol, like writing to a variable. - Write = 3 -}; -MAKE_REFLECT_TYPE_PROXY(lsDocumentHighlightKind); - -// A document highlight is a range inside a text document which deserves -// special attention. Usually a document highlight is visualized by changing -// the background color of its range. -struct lsDocumentHighlight { - // The range this highlight applies to. - lsRange range; - - // The highlight kind, default is DocumentHighlightKind.Text. - lsDocumentHighlightKind kind = lsDocumentHighlightKind::Text; - - // ccls extension - Role role = Role::None; -}; -MAKE_REFLECT_STRUCT(lsDocumentHighlight, range, kind, role); - struct lsSymbolInformation { std::string_view name; lsSymbolKind kind; lsLocation location; - std::string_view containerName; + std::optional containerName; }; MAKE_REFLECT_STRUCT(lsSymbolInformation, name, kind, location, containerName); diff --git a/src/test.cc b/src/test.cc index d2fb971a..57af162c 100644 --- a/src/test.cc +++ b/src/test.cc @@ -15,13 +15,17 @@ limitations under the License. #include "test.h" +#include "clang_complete.hh" #include "filesystem.hh" #include "indexer.h" +#include "pipeline.hh" #include "platform.h" #include "serializer.h" #include "utils.h" #include +#include +using namespace llvm; #include #include @@ -79,6 +83,12 @@ struct TextReplacer { } }; +void TrimInPlace(std::string &s) { + auto f = [](char c) { return !isspace(c); }; + s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); + s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); +} + void ParseTestExpectation( const std::string &filename, const std::vector &lines_with_endings, TextReplacer *replacer, @@ -88,7 +98,7 @@ void ParseTestExpectation( { bool in_output = false; for (std::string line : lines_with_endings) { - TrimInPlace(line); + line = StringRef(line).trim().str(); if (StartsWith(line, "EXTRA_FLAGS:")) { assert(!in_output && "multiple EXTRA_FLAGS sections"); @@ -124,8 +134,7 @@ void ParseTestExpectation( // one token assume it is a filename. std::vector tokens = SplitString(line_with_ending, " "); if (tokens.size() > 1) { - active_output_filename = tokens[1]; - TrimInPlace(active_output_filename); + active_output_filename = StringRef(tokens[1]).trim().str(); } else { active_output_filename = filename; } @@ -258,6 +267,9 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { bool update_all = false; // FIXME: show diagnostics in STL/headers when running tests. At the moment // this can be done by constructing ClangIndex index(1, 1); + CompletionManager completion( + nullptr, nullptr, [&](std::string, std::vector) {}, + [](lsRequestId id) {}); GetFilesInFolder( "index_tests", true /*recursive*/, true /*add_folder_to_path*/, [&](const std::string &path) { @@ -301,48 +313,19 @@ bool RunIndexTests(const std::string &filter_path, bool enable_update) { // Run test. g_config = new Config; VFS vfs; - auto dbs = ccls::idx::Index(&vfs, "", path, flags, {}); + WorkingFiles wfiles; + std::vector cargs; + for (auto &arg : flags) + cargs.push_back(arg.c_str()); + bool ok; + auto dbs = ccls::idx::Index(&completion, &wfiles, &vfs, "", path, cargs, {}, ok); for (const auto &entry : all_expected_output) { const std::string &expected_path = entry.first; std::string expected_output = text_replacer.Apply(entry.second); - // FIXME: promote to utils, find and remove duplicates (ie, - // ccls_call_tree.cc, maybe something in project.cc). - auto basename = [](const std::string &path) -> std::string { - size_t last_index = path.find_last_of('/'); - if (last_index == std::string::npos) - return path; - return path.substr(last_index + 1); - }; - // Get output from index operation. IndexFile *db = FindDbForPathEnding(expected_path, dbs); - if (db && !db->diagnostics_.empty()) { - printf("For %s\n", path.c_str()); - for (const lsDiagnostic &diagnostic : db->diagnostics_) { - printf(" "); - if (diagnostic.severity) - switch (*diagnostic.severity) { - case lsDiagnosticSeverity::Error: - printf("error "); - break; - case lsDiagnosticSeverity::Warning: - printf("warning "); - break; - case lsDiagnosticSeverity::Information: - printf("information "); - break; - case lsDiagnosticSeverity::Hint: - printf("hint "); - break; - } - printf("%s:%s-%s:%s\n", basename(db->path).c_str(), - diagnostic.range.start.ToString().c_str(), - diagnostic.range.end.ToString().c_str(), - diagnostic.message.c_str()); - } - } std::string actual_output = "{}"; if (db) { VerifySerializeToFrom(db); diff --git a/src/threaded_queue.h b/src/threaded_queue.h index c14307a3..d72f06d7 100644 --- a/src/threaded_queue.h +++ b/src/threaded_queue.h @@ -48,8 +48,7 @@ private: } template void unlock_impl(std::index_sequence) { - (void)std::initializer_list{ - (std::get(tuple_)->mutex_.unlock(), 0)...}; + (std::get(tuple_)->mutex_.unlock(), ...); } std::tuple tuple_; diff --git a/src/utils.cc b/src/utils.cc index 36a7e0e4..6a2f9e50 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -15,13 +15,16 @@ limitations under the License. #include "utils.h" -#include "filesystem.hh" -using namespace llvm; #include "log.hh" #include "platform.h" #include +#include +#include +#include +using namespace llvm; + #include #include #include @@ -29,17 +32,6 @@ using namespace llvm; #include #include #include -using namespace std::placeholders; - -void TrimInPlace(std::string &s) { - auto f = [](char c) { return !isspace(c); }; - s.erase(s.begin(), std::find_if(s.begin(), s.end(), f)); - s.erase(std::find_if(s.rbegin(), s.rend(), f).base(), s.end()); -} -std::string Trim(std::string s) { - TrimInPlace(s); - return s; -} uint64_t HashUsr(std::string_view s) { union { @@ -69,7 +61,8 @@ bool StartsWith(std::string_view s, std::string_view prefix) { } bool EndsWithAny(std::string_view s, const std::vector &ss) { - return std::any_of(ss.begin(), ss.end(), std::bind(EndsWith, s, _1)); + return std::any_of(ss.begin(), ss.end(), + std::bind(EndsWith, s, std::placeholders::_1)); } bool FindAnyPartial(const std::string &value, @@ -124,6 +117,22 @@ std::string EscapeFileName(std::string path) { return path; } +std::string ResolveIfRelative(const std::string &directory, + const std::string &path) { + if (sys::path::is_absolute(path)) + return path; + SmallString<256> Ret; + sys::path::append(Ret, directory, path); + return NormalizePath(Ret.str()); +} + +std::optional LastWriteTime(const std::string &path) { + sys::fs::file_status Status; + if (sys::fs::status(path, Status)) + return {}; + return sys::toTimeT(Status.getLastModificationTime()); +} + std::optional ReadContent(const std::string &filename) { char buf[4096]; std::string ret; @@ -147,13 +156,6 @@ void WriteToFile(const std::string &filename, const std::string &content) { fclose(f); } -std::optional LastWriteTime(const std::string &filename) { - sys::fs::file_status Status; - if (sys::fs::status(filename, Status)) - return {}; - return Status.getLastModificationTime().time_since_epoch().count(); -} - // Find discontinous |search| in |content|. // Return |found| and the count of skipped chars before found. int ReverseSubseqMatch(std::string_view pat, std::string_view text, diff --git a/src/utils.h b/src/utils.h index 973243fd..85e74c1d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -18,9 +18,7 @@ limitations under the License. #include #include -#include #include -#include #include #include @@ -28,9 +26,6 @@ namespace llvm { class StringRef; } -void TrimInPlace(std::string &s); -std::string Trim(std::string s); - uint64_t HashUsr(std::string_view s); uint64_t HashUsr(llvm::StringRef s); @@ -46,26 +41,6 @@ std::vector SplitString(const std::string &str, std::string LowerPathIfInsensitive(const std::string &path); -template -std::string StringJoinMap(const TValues &values, const TMap &map, - const std::string &sep = ", ") { - std::string result; - bool first = true; - for (auto &entry : values) { - if (!first) - result += sep; - first = false; - result += map(entry); - } - return result; -} - -template -std::string StringJoin(const TValues &values, const std::string &sep = ", ") { - return StringJoinMap(values, [](const std::string &entry) { return entry; }, - sep); -} - // Ensures that |path| ends in a slash. void EnsureEndsInSlash(std::string &path); @@ -73,9 +48,12 @@ void EnsureEndsInSlash(std::string &path); // e.g. foo/bar.c => foo_bar.c std::string EscapeFileName(std::string path); +std::string ResolveIfRelative(const std::string &directory, + const std::string &path); + +std::optional LastWriteTime(const std::string &path); std::optional ReadContent(const std::string &filename); void WriteToFile(const std::string &filename, const std::string &content); -std::optional LastWriteTime(const std::string &filename); int ReverseSubseqMatch(std::string_view pat, std::string_view text, int case_sensitivity); diff --git a/src/working_files.cc b/src/working_files.cc index 4f6ca27a..319a887e 100644 --- a/src/working_files.cc +++ b/src/working_files.cc @@ -387,31 +387,17 @@ std::string WorkingFile::FindClosestCallNameInBuffer( return buffer_content.substr(offset, start_offset - offset + 1); } -lsPosition WorkingFile::FindStableCompletionSource( - lsPosition position, bool *is_global_completion, - std::string *existing_completion, lsPosition *replace_end_pos) const { - *is_global_completion = true; - +lsPosition +WorkingFile::FindStableCompletionSource(lsPosition position, + std::string *existing_completion, + lsPosition *replace_end_pos) const { int start_offset = GetOffsetForPosition(position, buffer_content); int offset = start_offset; while (offset > 0) { char c = buffer_content[offset - 1]; - if (!isalnum(c) && c != '_') { - // Global completion is everything except for dot (.), arrow (->), and - // double colon (::) - if (c == '.') - *is_global_completion = false; - if (offset > 2) { - char pc = buffer_content[offset - 2]; - if (pc == ':' && c == ':') - *is_global_completion = false; - else if (pc == '-' && c == '>') - *is_global_completion = false; - } - + if (!isalnum(c) && c != '_') break; - } --offset; } @@ -442,6 +428,14 @@ WorkingFiles::GetFileByFilenameNoLock(const std::string &filename) { return nullptr; } +std::string WorkingFiles::GetContent(const std::string &filename) { + std::lock_guard lock(files_mutex); + for (auto &file : files) + if (file->filename == filename) + return file->buffer_content; + return ""; +} + void WorkingFiles::DoAction(const std::function &action) { std::lock_guard lock(files_mutex); action(); diff --git a/src/working_files.h b/src/working_files.h index b0ed01c7..caa001fd 100644 --- a/src/working_files.h +++ b/src/working_files.h @@ -82,7 +82,6 @@ struct WorkingFile { // The out param |existing_completion| is set to any existing completion // content the user has entered. lsPosition FindStableCompletionSource(lsPosition position, - bool *is_global_completion, std::string *existing_completion, lsPosition *replace_end_pos) const; @@ -108,6 +107,7 @@ struct WorkingFiles { // Find the file with the given filename. WorkingFile *GetFileByFilename(const std::string &filename); WorkingFile *GetFileByFilenameNoLock(const std::string &filename); + std::string GetContent(const std::string &filename); // Run |action| under the lock. void DoAction(const std::function &action);