2017-12-21 00:06:05 +08:00
|
|
|
//===-- XRefsTests.cpp ---------------------------*- C++ -*--------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-12-21 00:06:05 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "Annotations.h"
|
2018-02-14 01:47:16 +08:00
|
|
|
#include "Compiler.h"
|
2017-12-21 00:06:05 +08:00
|
|
|
#include "Matchers.h"
|
2019-09-04 17:46:06 +08:00
|
|
|
#include "ParsedAST.h"
|
2019-05-28 18:29:58 +08:00
|
|
|
#include "Protocol.h"
|
2019-09-26 15:27:43 +08:00
|
|
|
#include "SourceCode.h"
|
2018-02-15 21:15:47 +08:00
|
|
|
#include "SyncAPI.h"
|
2018-01-29 23:37:46 +08:00
|
|
|
#include "TestFS.h"
|
2019-07-10 01:59:50 +08:00
|
|
|
#include "TestIndex.h"
|
[clangd] Extract scoring/ranking logic, and shave yaks.
Summary:
Code completion scoring was embedded in CodeComplete.cpp, which is bad:
- awkward to test. The mechanisms (extracting info from index/sema) can be
unit-tested well, the policy (scoring) should be quantitatively measured.
Neither was easily possible, and debugging was hard.
The intermediate signal struct makes this easier.
- hard to reuse. This is a bug in workspaceSymbols: it just presents the
results in the index order, which is not sorted in practice, it needs to rank
them!
Also, index implementations care about scoring (both query-dependent and
independent) in order to truncate result lists appropriately.
The main yak shaved here is the build() function that had 3 variants across
unit tests is unified in TestTU.h (rather than adding a 4th variant).
Reviewers: ilya-biryukov
Subscribers: klimek, mgorny, ioeric, MaskRay, jkorous, mgrang, cfe-commits
Differential Revision: https://reviews.llvm.org/D46524
llvm-svn: 332378
2018-05-16 01:43:27 +08:00
|
|
|
#include "TestTU.h"
|
2017-12-21 00:06:05 +08:00
|
|
|
#include "XRefs.h"
|
2018-04-30 23:24:17 +08:00
|
|
|
#include "index/FileIndex.h"
|
2019-07-10 01:59:50 +08:00
|
|
|
#include "index/MemIndex.h"
|
2018-04-30 23:24:17 +08:00
|
|
|
#include "index/SymbolCollector.h"
|
2019-09-26 15:27:43 +08:00
|
|
|
#include "clang/AST/Decl.h"
|
|
|
|
#include "clang/Basic/SourceLocation.h"
|
2018-04-30 23:24:17 +08:00
|
|
|
#include "clang/Index/IndexingAction.h"
|
2019-05-28 18:29:58 +08:00
|
|
|
#include "llvm/ADT/None.h"
|
2019-09-26 15:27:43 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
#include "llvm/Support/Error.h"
|
2017-12-21 00:06:05 +08:00
|
|
|
#include "llvm/Support/Path.h"
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
#include "llvm/Support/ScopedPrinter.h"
|
[clangd] Extract scoring/ranking logic, and shave yaks.
Summary:
Code completion scoring was embedded in CodeComplete.cpp, which is bad:
- awkward to test. The mechanisms (extracting info from index/sema) can be
unit-tested well, the policy (scoring) should be quantitatively measured.
Neither was easily possible, and debugging was hard.
The intermediate signal struct makes this easier.
- hard to reuse. This is a bug in workspaceSymbols: it just presents the
results in the index order, which is not sorted in practice, it needs to rank
them!
Also, index implementations care about scoring (both query-dependent and
independent) in order to truncate result lists appropriately.
The main yak shaved here is the build() function that had 3 variants across
unit tests is unified in TestTU.h (rather than adding a 4th variant).
Reviewers: ilya-biryukov
Subscribers: klimek, mgorny, ioeric, MaskRay, jkorous, mgrang, cfe-commits
Differential Revision: https://reviews.llvm.org/D46524
llvm-svn: 332378
2018-05-16 01:43:27 +08:00
|
|
|
#include "gmock/gmock.h"
|
2017-12-21 00:06:05 +08:00
|
|
|
#include "gtest/gtest.h"
|
2019-06-13 16:51:44 +08:00
|
|
|
#include <string>
|
2019-09-26 15:27:43 +08:00
|
|
|
#include <vector>
|
2017-12-21 00:06:05 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
2018-10-20 23:30:37 +08:00
|
|
|
|
2019-05-06 18:08:47 +08:00
|
|
|
using ::testing::ElementsAre;
|
|
|
|
using ::testing::IsEmpty;
|
|
|
|
using ::testing::Matcher;
|
|
|
|
using ::testing::UnorderedElementsAreArray;
|
2017-12-21 00:06:05 +08:00
|
|
|
|
2018-11-28 18:30:42 +08:00
|
|
|
MATCHER_P2(FileRange, File, Range, "") {
|
|
|
|
return Location{URIForFile::canonicalize(File, testRoot()), Range} == arg;
|
|
|
|
}
|
|
|
|
|
2017-12-21 00:06:05 +08:00
|
|
|
// Extracts ranges from an annotated example, and constructs a matcher for a
|
|
|
|
// highlight set. Ranges should be named $read/$write as appropriate.
|
|
|
|
Matcher<const std::vector<DocumentHighlight> &>
|
|
|
|
HighlightsFrom(const Annotations &Test) {
|
|
|
|
std::vector<DocumentHighlight> Expected;
|
|
|
|
auto Add = [&](const Range &R, DocumentHighlightKind K) {
|
|
|
|
Expected.emplace_back();
|
|
|
|
Expected.back().range = R;
|
|
|
|
Expected.back().kind = K;
|
|
|
|
};
|
|
|
|
for (const auto &Range : Test.ranges())
|
|
|
|
Add(Range, DocumentHighlightKind::Text);
|
|
|
|
for (const auto &Range : Test.ranges("read"))
|
|
|
|
Add(Range, DocumentHighlightKind::Read);
|
|
|
|
for (const auto &Range : Test.ranges("write"))
|
|
|
|
Add(Range, DocumentHighlightKind::Write);
|
|
|
|
return UnorderedElementsAreArray(Expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(HighlightsTest, All) {
|
|
|
|
const char *Tests[] = {
|
|
|
|
R"cpp(// Local variable
|
|
|
|
int main() {
|
|
|
|
int [[bonjour]];
|
|
|
|
$write[[^bonjour]] = 2;
|
|
|
|
int test1 = $read[[bonjour]];
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Struct
|
|
|
|
namespace ns1 {
|
|
|
|
struct [[MyClass]] {
|
|
|
|
static void foo([[MyClass]]*) {}
|
|
|
|
};
|
|
|
|
} // namespace ns1
|
|
|
|
int main() {
|
|
|
|
ns1::[[My^Class]]* Params;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Function
|
|
|
|
int [[^foo]](int) {}
|
|
|
|
int main() {
|
|
|
|
[[foo]]([[foo]](42));
|
|
|
|
auto *X = &[[foo]];
|
|
|
|
}
|
|
|
|
)cpp",
|
2019-02-11 21:03:08 +08:00
|
|
|
|
|
|
|
R"cpp(// Function parameter in decl
|
|
|
|
void foo(int [[^bar]]);
|
|
|
|
)cpp",
|
2017-12-21 00:06:05 +08:00
|
|
|
};
|
|
|
|
for (const char *Test : Tests) {
|
|
|
|
Annotations T(Test);
|
[clangd] Extract scoring/ranking logic, and shave yaks.
Summary:
Code completion scoring was embedded in CodeComplete.cpp, which is bad:
- awkward to test. The mechanisms (extracting info from index/sema) can be
unit-tested well, the policy (scoring) should be quantitatively measured.
Neither was easily possible, and debugging was hard.
The intermediate signal struct makes this easier.
- hard to reuse. This is a bug in workspaceSymbols: it just presents the
results in the index order, which is not sorted in practice, it needs to rank
them!
Also, index implementations care about scoring (both query-dependent and
independent) in order to truncate result lists appropriately.
The main yak shaved here is the build() function that had 3 variants across
unit tests is unified in TestTU.h (rather than adding a 4th variant).
Reviewers: ilya-biryukov
Subscribers: klimek, mgorny, ioeric, MaskRay, jkorous, mgrang, cfe-commits
Differential Revision: https://reviews.llvm.org/D46524
llvm-svn: 332378
2018-05-16 01:43:27 +08:00
|
|
|
auto AST = TestTU::withCode(T.code()).build();
|
[clangd] Pass Context implicitly using TLS.
Summary:
Instead of passing Context explicitly around, we now have a thread-local
Context object `Context::current()` which is an implicit argument to
every function.
Most manipulation of this should use the WithContextValue helper, which
augments the current Context to add a single KV pair, and restores the
old context on destruction.
Advantages are:
- less boilerplate in functions that just propagate contexts
- reading most code doesn't require understanding context at all, and
using context as values in fewer places still
- fewer options to pass the "wrong" context when it changes within a
scope (e.g. when using Span)
- contexts pass through interfaces we can't modify, such as VFS
- propagating contexts across threads was slightly tricky (e.g.
copy vs move, no move-init in lambdas), and is now encapsulated in
the threadpool
Disadvantages are all the usual TLS stuff - hidden magic, and
potential for higher memory usage on threads that don't use the
context. (In practice, it's just one pointer)
Reviewers: ilya-biryukov
Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D42517
llvm-svn: 323872
2018-01-31 21:40:48 +08:00
|
|
|
EXPECT_THAT(findDocumentHighlights(AST, T.point()), HighlightsFrom(T))
|
2017-12-21 00:06:05 +08:00
|
|
|
<< Test;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
MATCHER_P3(Sym, Name, Decl, DefOrNone, "") {
|
|
|
|
llvm::Optional<Range> Def = DefOrNone;
|
|
|
|
if (Name != arg.Name) {
|
|
|
|
*result_listener << "Name is " << arg.Name;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (Decl != arg.PreferredDeclaration.range) {
|
|
|
|
*result_listener << "Declaration is "
|
|
|
|
<< llvm::to_string(arg.PreferredDeclaration);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (Def && !arg.Definition) {
|
|
|
|
*result_listener << "Has no definition";
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (Def && arg.Definition->range != *Def) {
|
|
|
|
*result_listener << "Definition is " << llvm::to_string(arg.Definition);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2019-05-06 18:08:47 +08:00
|
|
|
::testing::Matcher<LocatedSymbol> Sym(std::string Name, Range Decl) {
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
return Sym(Name, Decl, llvm::None);
|
|
|
|
}
|
|
|
|
MATCHER_P(Sym, Name, "") { return arg.Name == Name; }
|
|
|
|
|
2017-12-21 00:06:05 +08:00
|
|
|
MATCHER_P(RangeIs, R, "") { return arg.range == R; }
|
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
TEST(LocateSymbol, WithIndex) {
|
2018-04-30 23:24:17 +08:00
|
|
|
Annotations SymbolHeader(R"cpp(
|
|
|
|
class $forward[[Forward]];
|
|
|
|
class $foo[[Foo]] {};
|
|
|
|
|
|
|
|
void $f1[[f1]]();
|
|
|
|
|
|
|
|
inline void $f2[[f2]]() {}
|
|
|
|
)cpp");
|
|
|
|
Annotations SymbolCpp(R"cpp(
|
|
|
|
class $forward[[forward]] {};
|
|
|
|
void $f1[[f1]]() {}
|
|
|
|
)cpp");
|
|
|
|
|
[clangd] Extract scoring/ranking logic, and shave yaks.
Summary:
Code completion scoring was embedded in CodeComplete.cpp, which is bad:
- awkward to test. The mechanisms (extracting info from index/sema) can be
unit-tested well, the policy (scoring) should be quantitatively measured.
Neither was easily possible, and debugging was hard.
The intermediate signal struct makes this easier.
- hard to reuse. This is a bug in workspaceSymbols: it just presents the
results in the index order, which is not sorted in practice, it needs to rank
them!
Also, index implementations care about scoring (both query-dependent and
independent) in order to truncate result lists appropriately.
The main yak shaved here is the build() function that had 3 variants across
unit tests is unified in TestTU.h (rather than adding a 4th variant).
Reviewers: ilya-biryukov
Subscribers: klimek, mgorny, ioeric, MaskRay, jkorous, mgrang, cfe-commits
Differential Revision: https://reviews.llvm.org/D46524
llvm-svn: 332378
2018-05-16 01:43:27 +08:00
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.Code = std::string(SymbolCpp.code());
|
|
|
|
TU.HeaderCode = std::string(SymbolHeader.code());
|
[clangd] Extract scoring/ranking logic, and shave yaks.
Summary:
Code completion scoring was embedded in CodeComplete.cpp, which is bad:
- awkward to test. The mechanisms (extracting info from index/sema) can be
unit-tested well, the policy (scoring) should be quantitatively measured.
Neither was easily possible, and debugging was hard.
The intermediate signal struct makes this easier.
- hard to reuse. This is a bug in workspaceSymbols: it just presents the
results in the index order, which is not sorted in practice, it needs to rank
them!
Also, index implementations care about scoring (both query-dependent and
independent) in order to truncate result lists appropriately.
The main yak shaved here is the build() function that had 3 variants across
unit tests is unified in TestTU.h (rather than adding a 4th variant).
Reviewers: ilya-biryukov
Subscribers: klimek, mgorny, ioeric, MaskRay, jkorous, mgrang, cfe-commits
Differential Revision: https://reviews.llvm.org/D46524
llvm-svn: 332378
2018-05-16 01:43:27 +08:00
|
|
|
auto Index = TU.index();
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
auto LocateWithIndex = [&Index](const Annotations &Main) {
|
[clangd] Extract scoring/ranking logic, and shave yaks.
Summary:
Code completion scoring was embedded in CodeComplete.cpp, which is bad:
- awkward to test. The mechanisms (extracting info from index/sema) can be
unit-tested well, the policy (scoring) should be quantitatively measured.
Neither was easily possible, and debugging was hard.
The intermediate signal struct makes this easier.
- hard to reuse. This is a bug in workspaceSymbols: it just presents the
results in the index order, which is not sorted in practice, it needs to rank
them!
Also, index implementations care about scoring (both query-dependent and
independent) in order to truncate result lists appropriately.
The main yak shaved here is the build() function that had 3 variants across
unit tests is unified in TestTU.h (rather than adding a 4th variant).
Reviewers: ilya-biryukov
Subscribers: klimek, mgorny, ioeric, MaskRay, jkorous, mgrang, cfe-commits
Differential Revision: https://reviews.llvm.org/D46524
llvm-svn: 332378
2018-05-16 01:43:27 +08:00
|
|
|
auto AST = TestTU::withCode(Main.code()).build();
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
return clangd::locateSymbolAt(AST, Main.point(), Index.get());
|
2018-04-30 23:24:17 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
Annotations Test(R"cpp(// only declaration in AST.
|
|
|
|
void [[f1]]();
|
|
|
|
int main() {
|
|
|
|
^f1();
|
|
|
|
}
|
|
|
|
)cpp");
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(LocateWithIndex(Test),
|
|
|
|
ElementsAre(Sym("f1", Test.range(), SymbolCpp.range("f1"))));
|
2018-04-30 23:24:17 +08:00
|
|
|
|
|
|
|
Test = Annotations(R"cpp(// definition in AST.
|
|
|
|
void [[f1]]() {}
|
|
|
|
int main() {
|
|
|
|
^f1();
|
|
|
|
}
|
|
|
|
)cpp");
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(LocateWithIndex(Test),
|
|
|
|
ElementsAre(Sym("f1", SymbolHeader.range("f1"), Test.range())));
|
2018-04-30 23:24:17 +08:00
|
|
|
|
|
|
|
Test = Annotations(R"cpp(// forward declaration in AST.
|
|
|
|
class [[Foo]];
|
|
|
|
F^oo* create();
|
|
|
|
)cpp");
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(LocateWithIndex(Test),
|
|
|
|
ElementsAre(Sym("Foo", Test.range(), SymbolHeader.range("foo"))));
|
2018-04-30 23:24:17 +08:00
|
|
|
|
2020-01-04 23:28:41 +08:00
|
|
|
Test = Annotations(R"cpp(// definition in AST.
|
2018-04-30 23:24:17 +08:00
|
|
|
class [[Forward]] {};
|
|
|
|
F^orward create();
|
|
|
|
)cpp");
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
LocateWithIndex(Test),
|
|
|
|
ElementsAre(Sym("Forward", SymbolHeader.range("forward"), Test.range())));
|
2018-04-30 23:24:17 +08:00
|
|
|
}
|
|
|
|
|
2019-02-11 23:05:29 +08:00
|
|
|
TEST(LocateSymbol, WithIndexPreferredLocation) {
|
|
|
|
Annotations SymbolHeader(R"cpp(
|
2019-05-03 20:11:14 +08:00
|
|
|
class $p[[Proto]] {};
|
|
|
|
void $f[[func]]() {};
|
2019-02-11 23:05:29 +08:00
|
|
|
)cpp");
|
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.HeaderCode = std::string(SymbolHeader.code());
|
2019-02-11 23:05:29 +08:00
|
|
|
TU.HeaderFilename = "x.proto"; // Prefer locations in codegen files.
|
|
|
|
auto Index = TU.index();
|
|
|
|
|
|
|
|
Annotations Test(R"cpp(// only declaration in AST.
|
|
|
|
// Shift to make range different.
|
2019-05-03 20:11:14 +08:00
|
|
|
class Proto;
|
|
|
|
void func() {}
|
|
|
|
P$p^roto* create() {
|
|
|
|
fu$f^nc();
|
|
|
|
return nullptr;
|
|
|
|
}
|
2019-02-11 23:05:29 +08:00
|
|
|
)cpp");
|
|
|
|
|
|
|
|
auto AST = TestTU::withCode(Test.code()).build();
|
2019-05-03 20:11:14 +08:00
|
|
|
{
|
|
|
|
auto Locs = clangd::locateSymbolAt(AST, Test.point("p"), Index.get());
|
|
|
|
auto CodeGenLoc = SymbolHeader.range("p");
|
|
|
|
EXPECT_THAT(Locs, ElementsAre(Sym("Proto", CodeGenLoc, CodeGenLoc)));
|
|
|
|
}
|
|
|
|
{
|
|
|
|
auto Locs = clangd::locateSymbolAt(AST, Test.point("f"), Index.get());
|
|
|
|
auto CodeGenLoc = SymbolHeader.range("f");
|
|
|
|
EXPECT_THAT(Locs, ElementsAre(Sym("func", CodeGenLoc, CodeGenLoc)));
|
|
|
|
}
|
2019-02-11 23:05:29 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
TEST(LocateSymbol, All) {
|
|
|
|
// Ranges in tests:
|
|
|
|
// $decl is the declaration location (if absent, no symbol is located)
|
|
|
|
// $def is the definition location (if absent, symbol has no definition)
|
|
|
|
// unnamed range becomes both $decl and $def.
|
2017-12-21 00:06:05 +08:00
|
|
|
const char *Tests[] = {
|
|
|
|
R"cpp(// Local variable
|
|
|
|
int main() {
|
2018-03-09 22:00:34 +08:00
|
|
|
int [[bonjour]];
|
2017-12-21 00:06:05 +08:00
|
|
|
^bonjour = 2;
|
|
|
|
int test1 = bonjour;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Struct
|
|
|
|
namespace ns1 {
|
2018-03-09 22:00:34 +08:00
|
|
|
struct [[MyClass]] {};
|
2017-12-21 00:06:05 +08:00
|
|
|
} // namespace ns1
|
|
|
|
int main() {
|
|
|
|
ns1::My^Class* Params;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Function definition via pointer
|
2020-01-02 14:08:05 +08:00
|
|
|
void [[foo]](int) {}
|
2017-12-21 00:06:05 +08:00
|
|
|
int main() {
|
|
|
|
auto *X = &^foo;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Function declaration via call
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
int $decl[[foo]](int);
|
2017-12-21 00:06:05 +08:00
|
|
|
int main() {
|
|
|
|
return ^foo(42);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Field
|
2018-03-09 22:00:34 +08:00
|
|
|
struct Foo { int [[x]]; };
|
2017-12-21 00:06:05 +08:00
|
|
|
int main() {
|
|
|
|
Foo bar;
|
2020-01-02 14:08:05 +08:00
|
|
|
(void)bar.^x;
|
2017-12-21 00:06:05 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Field, member initializer
|
|
|
|
struct Foo {
|
2018-03-09 22:00:34 +08:00
|
|
|
int [[x]];
|
2017-12-21 00:06:05 +08:00
|
|
|
Foo() : ^x(0) {}
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Field, field designator
|
2018-03-09 22:00:34 +08:00
|
|
|
struct Foo { int [[x]]; };
|
2017-12-21 00:06:05 +08:00
|
|
|
int main() {
|
|
|
|
Foo bar = { .^x = 2 };
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Method call
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
struct Foo { int $decl[[x]](); };
|
2017-12-21 00:06:05 +08:00
|
|
|
int main() {
|
|
|
|
Foo bar;
|
|
|
|
bar.^x();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Typedef
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
typedef int $decl[[Foo]];
|
2017-12-21 00:06:05 +08:00
|
|
|
int main() {
|
|
|
|
^Foo bar;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Template type parameter
|
2019-02-21 17:55:00 +08:00
|
|
|
template <typename [[T]]>
|
2017-12-21 00:06:05 +08:00
|
|
|
void foo() { ^T t; }
|
2019-02-21 17:55:00 +08:00
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Template template type parameter
|
|
|
|
template <template<typename> class [[T]]>
|
|
|
|
void foo() { ^T<int> t; }
|
|
|
|
)cpp",
|
2017-12-21 00:06:05 +08:00
|
|
|
|
|
|
|
R"cpp(// Namespace
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
namespace $decl[[ns]] {
|
2020-01-02 14:08:05 +08:00
|
|
|
struct Foo { static void bar(); };
|
2018-03-09 22:00:34 +08:00
|
|
|
} // namespace ns
|
2017-12-21 00:06:05 +08:00
|
|
|
int main() { ^ns::Foo::bar(); }
|
|
|
|
)cpp",
|
|
|
|
|
2018-03-13 20:30:59 +08:00
|
|
|
R"cpp(// Macro
|
|
|
|
class TTT { public: int a; };
|
2018-03-13 22:31:31 +08:00
|
|
|
#define [[FF]](S) if (int b = S.a) {}
|
2018-03-13 20:30:59 +08:00
|
|
|
void f() {
|
|
|
|
TTT t;
|
|
|
|
F^F(t);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
2018-04-09 22:28:52 +08:00
|
|
|
R"cpp(// Macro argument
|
|
|
|
int [[i]];
|
|
|
|
#define ADDRESSOF(X) &X;
|
|
|
|
int *j = ADDRESSOF(^i);
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Symbol concatenated inside macro (not supported)
|
|
|
|
int *pi;
|
2020-01-02 14:08:05 +08:00
|
|
|
#define POINTER(X) p ## X;
|
2018-04-09 22:28:52 +08:00
|
|
|
int i = *POINTER(^i);
|
|
|
|
)cpp",
|
|
|
|
|
2018-01-12 22:21:10 +08:00
|
|
|
R"cpp(// Forward class declaration
|
|
|
|
class Foo;
|
2018-03-09 22:00:34 +08:00
|
|
|
class [[Foo]] {};
|
2018-01-12 22:21:10 +08:00
|
|
|
F^oo* foo();
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Function declaration
|
|
|
|
void foo();
|
|
|
|
void g() { f^oo(); }
|
2018-03-09 22:00:34 +08:00
|
|
|
void [[foo]]() {}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
#define FF(name) class name##_Test {};
|
|
|
|
[[FF]](my);
|
|
|
|
void f() { my^_Test a; }
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
#define FF() class [[Test]] {};
|
|
|
|
FF();
|
|
|
|
void f() { T^est a; }
|
2018-01-12 22:21:10 +08:00
|
|
|
)cpp",
|
2019-02-18 22:23:19 +08:00
|
|
|
|
|
|
|
R"cpp(// explicit template specialization
|
|
|
|
template <typename T>
|
|
|
|
struct Foo { void bar() {} };
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct [[Foo]]<int> { void bar() {} };
|
|
|
|
|
|
|
|
void foo() {
|
|
|
|
Foo<char> abc;
|
|
|
|
Fo^o<int> b;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// implicit template specialization
|
|
|
|
template <typename T>
|
|
|
|
struct [[Foo]] { void bar() {} };
|
|
|
|
template <>
|
|
|
|
struct Foo<int> { void bar() {} };
|
|
|
|
void foo() {
|
|
|
|
Fo^o<char> abc;
|
|
|
|
Foo<int> b;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// partial template specialization
|
|
|
|
template <typename T>
|
|
|
|
struct Foo { void bar() {} };
|
|
|
|
template <typename T>
|
|
|
|
struct [[Foo]]<T*> { void bar() {} };
|
|
|
|
^Foo<int*> x;
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// function template specializations
|
|
|
|
template <class T>
|
|
|
|
void foo(T) {}
|
|
|
|
template <>
|
|
|
|
void [[foo]](int) {}
|
|
|
|
void bar() {
|
|
|
|
fo^o(10);
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// variable template decls
|
|
|
|
template <class T>
|
|
|
|
T var = T();
|
|
|
|
|
|
|
|
template <>
|
|
|
|
double [[var]]<int> = 10;
|
|
|
|
|
|
|
|
double y = va^r<int>;
|
|
|
|
)cpp",
|
2019-02-21 22:48:33 +08:00
|
|
|
|
|
|
|
R"cpp(// No implicit constructors
|
2020-01-02 14:08:05 +08:00
|
|
|
struct X {
|
2019-02-21 22:48:33 +08:00
|
|
|
X(X&& x) = default;
|
|
|
|
};
|
2020-01-02 14:08:05 +08:00
|
|
|
X $decl[[makeX]]();
|
2019-02-21 22:48:33 +08:00
|
|
|
void foo() {
|
|
|
|
auto x = m^akeX();
|
|
|
|
}
|
|
|
|
)cpp",
|
2019-10-01 19:03:56 +08:00
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
struct X {
|
2020-01-02 14:08:05 +08:00
|
|
|
X& $decl[[operator]]++();
|
2019-10-01 19:03:56 +08:00
|
|
|
};
|
|
|
|
void foo(X& x) {
|
|
|
|
+^+x;
|
|
|
|
}
|
|
|
|
)cpp",
|
2019-12-06 05:29:59 +08:00
|
|
|
|
|
|
|
R"cpp(// Declaration of explicit template specialization
|
|
|
|
template <typename T>
|
|
|
|
struct $decl[[Foo]] {};
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct Fo^o<int> {};
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Declaration of partial template specialization
|
|
|
|
template <typename T>
|
|
|
|
struct $decl[[Foo]] {};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct Fo^o<T*> {};
|
2019-12-06 07:29:32 +08:00
|
|
|
)cpp",
|
|
|
|
|
2020-01-25 01:21:47 +08:00
|
|
|
R"cpp(// Override specifier jumps to overridden method
|
|
|
|
class Y { virtual void $decl[[a]]() = 0; };
|
|
|
|
class X : Y { void a() ^override {} };
|
|
|
|
)cpp",
|
|
|
|
|
2020-01-30 19:45:43 +08:00
|
|
|
R"cpp(// Final specifier jumps to overridden method
|
|
|
|
class Y { virtual void $decl[[a]]() = 0; };
|
|
|
|
class X : Y { void a() ^final {} };
|
|
|
|
)cpp",
|
|
|
|
|
2019-12-06 07:29:32 +08:00
|
|
|
R"cpp(// Heuristic resolution of dependent method
|
|
|
|
template <typename T>
|
|
|
|
struct S {
|
|
|
|
void [[bar]]() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void foo(S<T> arg) {
|
|
|
|
arg.ba^r();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Heuristic resolution of dependent method via this->
|
|
|
|
template <typename T>
|
|
|
|
struct S {
|
|
|
|
void [[foo]]() {
|
|
|
|
this->fo^o();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Heuristic resolution of dependent static method
|
|
|
|
template <typename T>
|
|
|
|
struct S {
|
|
|
|
static void [[bar]]() {}
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
void foo() {
|
|
|
|
S<T>::ba^r();
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
2019-12-16 09:42:25 +08:00
|
|
|
R"cpp(// Heuristic resolution of dependent method
|
2019-12-06 07:29:32 +08:00
|
|
|
// invoked via smart pointer
|
2019-12-16 09:42:25 +08:00
|
|
|
template <typename> struct S { void [[foo]]() {} };
|
2019-12-06 07:29:32 +08:00
|
|
|
template <typename T> struct unique_ptr {
|
|
|
|
T* operator->();
|
|
|
|
};
|
|
|
|
template <typename T>
|
|
|
|
void test(unique_ptr<S<T>>& V) {
|
|
|
|
V->fo^o();
|
|
|
|
}
|
2019-12-06 05:29:59 +08:00
|
|
|
)cpp"};
|
2017-12-21 00:06:05 +08:00
|
|
|
for (const char *Test : Tests) {
|
|
|
|
Annotations T(Test);
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
llvm::Optional<Range> WantDecl;
|
|
|
|
llvm::Optional<Range> WantDef;
|
|
|
|
if (!T.ranges().empty())
|
|
|
|
WantDecl = WantDef = T.range();
|
|
|
|
if (!T.ranges("decl").empty())
|
|
|
|
WantDecl = T.range("decl");
|
|
|
|
if (!T.ranges("def").empty())
|
|
|
|
WantDef = T.range("def");
|
|
|
|
|
2019-10-13 21:15:27 +08:00
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.Code = std::string(T.code());
|
2019-10-13 21:15:27 +08:00
|
|
|
|
|
|
|
// FIXME: Auto-completion in a template requires disabling delayed template
|
|
|
|
// parsing.
|
|
|
|
TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
|
|
|
|
|
2020-01-02 14:08:05 +08:00
|
|
|
auto AST = TU.build();
|
|
|
|
auto Results = locateSymbolAt(AST, T.point());
|
|
|
|
|
|
|
|
if (!WantDecl) {
|
|
|
|
EXPECT_THAT(Results, IsEmpty()) << Test;
|
|
|
|
} else {
|
|
|
|
ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
|
|
|
|
EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
|
|
|
|
llvm::Optional<Range> GotDef;
|
|
|
|
if (Results[0].Definition)
|
|
|
|
GotDef = Results[0].Definition->range;
|
|
|
|
EXPECT_EQ(WantDef, GotDef) << Test;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// LocateSymbol test cases that produce warnings.
|
|
|
|
// These are separated out from All so that in All we can assert
|
|
|
|
// that there are no diagnostics.
|
|
|
|
TEST(LocateSymbol, Warnings) {
|
|
|
|
const char *Tests[] = {
|
|
|
|
R"cpp(// Field, GNU old-style field designator
|
|
|
|
struct Foo { int [[x]]; };
|
|
|
|
int main() {
|
|
|
|
Foo bar = { ^x : 1 };
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Macro
|
|
|
|
#define MACRO 0
|
|
|
|
#define [[MACRO]] 1
|
|
|
|
int main() { return ^MACRO; }
|
|
|
|
#define MACRO 2
|
|
|
|
#undef macro
|
|
|
|
)cpp",
|
|
|
|
};
|
|
|
|
|
|
|
|
for (const char *Test : Tests) {
|
|
|
|
Annotations T(Test);
|
|
|
|
llvm::Optional<Range> WantDecl;
|
|
|
|
llvm::Optional<Range> WantDef;
|
|
|
|
if (!T.ranges().empty())
|
|
|
|
WantDecl = WantDef = T.range();
|
|
|
|
if (!T.ranges("decl").empty())
|
|
|
|
WantDecl = T.range("decl");
|
|
|
|
if (!T.ranges("def").empty())
|
|
|
|
WantDef = T.range("def");
|
|
|
|
|
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.Code = std::string(T.code());
|
2020-01-02 14:08:05 +08:00
|
|
|
|
2019-10-13 21:15:27 +08:00
|
|
|
auto AST = TU.build();
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
auto Results = locateSymbolAt(AST, T.point());
|
|
|
|
|
|
|
|
if (!WantDecl) {
|
|
|
|
EXPECT_THAT(Results, IsEmpty()) << Test;
|
|
|
|
} else {
|
|
|
|
ASSERT_THAT(Results, ::testing::SizeIs(1)) << Test;
|
|
|
|
EXPECT_EQ(Results[0].PreferredDeclaration.range, *WantDecl) << Test;
|
|
|
|
llvm::Optional<Range> GotDef;
|
|
|
|
if (Results[0].Definition)
|
|
|
|
GotDef = Results[0].Definition->range;
|
|
|
|
EXPECT_EQ(WantDef, GotDef) << Test;
|
|
|
|
}
|
2017-12-21 00:06:05 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
TEST(LocateSymbol, Ambiguous) {
|
2018-09-05 20:00:15 +08:00
|
|
|
auto T = Annotations(R"cpp(
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
struct Foo {
|
|
|
|
Foo();
|
|
|
|
Foo(Foo&&);
|
2019-10-18 06:48:39 +08:00
|
|
|
$ConstructorLoc[[Foo]](const char*);
|
2018-09-05 20:00:15 +08:00
|
|
|
};
|
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Foo f();
|
2018-09-05 20:00:15 +08:00
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
void g(Foo foo);
|
2018-09-05 20:00:15 +08:00
|
|
|
|
|
|
|
void call() {
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
const char* str = "123";
|
2018-09-05 20:00:15 +08:00
|
|
|
Foo a = $1^str;
|
|
|
|
Foo b = Foo($2^str);
|
|
|
|
Foo c = $3^f();
|
|
|
|
$4^g($5^f());
|
|
|
|
g($6^str);
|
2019-02-21 22:48:33 +08:00
|
|
|
Foo ab$7^c;
|
|
|
|
Foo ab$8^cd("asdf");
|
|
|
|
Foo foox = Fo$9^o("asdf");
|
2019-10-18 06:48:39 +08:00
|
|
|
Foo abcde$10^("asdf");
|
|
|
|
Foo foox2 = Foo$11^("asdf");
|
2018-09-05 20:00:15 +08:00
|
|
|
}
|
2019-12-06 07:29:32 +08:00
|
|
|
|
|
|
|
template <typename T>
|
|
|
|
struct S {
|
|
|
|
void $NonstaticOverload1[[bar]](int);
|
|
|
|
void $NonstaticOverload2[[bar]](float);
|
|
|
|
|
|
|
|
static void $StaticOverload1[[baz]](int);
|
|
|
|
static void $StaticOverload2[[baz]](float);
|
|
|
|
};
|
|
|
|
|
|
|
|
template <typename T, typename U>
|
|
|
|
void dependent_call(S<T> s, U u) {
|
|
|
|
s.ba$12^r(u);
|
|
|
|
S<T>::ba$13^z(u);
|
|
|
|
}
|
2018-09-05 20:00:15 +08:00
|
|
|
)cpp");
|
2019-12-13 08:57:45 +08:00
|
|
|
auto TU = TestTU::withCode(T.code());
|
|
|
|
// FIXME: Go-to-definition in a template requires disabling delayed template
|
|
|
|
// parsing.
|
|
|
|
TU.ExtraArgs.push_back("-fno-delayed-template-parsing");
|
|
|
|
auto AST = TU.build();
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
// Ordered assertions are deliberate: we expect a predictable order.
|
2019-02-21 22:48:33 +08:00
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("1")), ElementsAre(Sym("str")));
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("2")), ElementsAre(Sym("str")));
|
2019-02-21 22:48:33 +08:00
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("3")), ElementsAre(Sym("f")));
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("4")), ElementsAre(Sym("g")));
|
2019-02-21 22:48:33 +08:00
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("5")), ElementsAre(Sym("f")));
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("6")), ElementsAre(Sym("str")));
|
2019-10-18 06:48:39 +08:00
|
|
|
// FIXME: Target the constructor as well.
|
2019-02-21 22:48:33 +08:00
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("7")), ElementsAre(Sym("abc")));
|
2019-10-18 06:48:39 +08:00
|
|
|
// FIXME: Target the constructor as well.
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("8")), ElementsAre(Sym("abcd")));
|
|
|
|
// FIXME: Target the constructor as well.
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("9")), ElementsAre(Sym("Foo")));
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("10")),
|
|
|
|
ElementsAre(Sym("Foo", T.range("ConstructorLoc"))));
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("11")),
|
|
|
|
ElementsAre(Sym("Foo", T.range("ConstructorLoc"))));
|
2019-12-06 07:29:32 +08:00
|
|
|
// These assertions are unordered because the order comes from
|
|
|
|
// CXXRecordDecl::lookupDependentName() which doesn't appear to provide
|
|
|
|
// an order guarantee.
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("12")),
|
|
|
|
UnorderedElementsAre(Sym("bar", T.range("NonstaticOverload1")),
|
|
|
|
Sym("bar", T.range("NonstaticOverload2"))));
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point("13")),
|
|
|
|
UnorderedElementsAre(Sym("baz", T.range("StaticOverload1")),
|
|
|
|
Sym("baz", T.range("StaticOverload2"))));
|
2018-09-05 20:00:15 +08:00
|
|
|
}
|
|
|
|
|
2019-05-24 00:48:47 +08:00
|
|
|
TEST(LocateSymbol, TemplateTypedefs) {
|
|
|
|
auto T = Annotations(R"cpp(
|
|
|
|
template <class T> struct function {};
|
|
|
|
template <class T> using callback = function<T()>;
|
|
|
|
|
|
|
|
c^allback<int> foo;
|
|
|
|
)cpp");
|
|
|
|
auto AST = TestTU::withCode(T.code()).build();
|
|
|
|
EXPECT_THAT(locateSymbolAt(AST, T.point()), ElementsAre(Sym("callback")));
|
|
|
|
}
|
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
TEST(LocateSymbol, RelPathsInCompileCommand) {
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
// The source is in "/clangd-test/src".
|
|
|
|
// We build in "/clangd-test/build".
|
|
|
|
|
2018-02-14 01:47:16 +08:00
|
|
|
Annotations SourceAnnotations(R"cpp(
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
#include "header_in_preamble.h"
|
2018-03-09 22:00:34 +08:00
|
|
|
int [[foo]];
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
#include "header_not_in_preamble.h"
|
|
|
|
int baz = f$p1^oo + bar_pre$p2^amble + bar_not_pre$p3^amble;
|
|
|
|
)cpp");
|
|
|
|
|
|
|
|
Annotations HeaderInPreambleAnnotations(R"cpp(
|
|
|
|
int [[bar_preamble]];
|
2018-02-14 01:47:16 +08:00
|
|
|
)cpp");
|
|
|
|
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
Annotations HeaderNotInPreambleAnnotations(R"cpp(
|
|
|
|
int [[bar_not_preamble]];
|
|
|
|
)cpp");
|
|
|
|
|
|
|
|
// Make the compilation paths appear as ../src/foo.cpp in the compile
|
|
|
|
// commands.
|
|
|
|
SmallString<32> RelPathPrefix("..");
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::sys::path::append(RelPathPrefix, "src");
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
std::string BuildDir = testPath("build");
|
|
|
|
MockCompilationDatabase CDB(BuildDir, RelPathPrefix);
|
|
|
|
|
2018-02-14 01:47:16 +08:00
|
|
|
MockFSProvider FS;
|
2020-01-24 21:08:56 +08:00
|
|
|
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
2018-02-14 01:47:16 +08:00
|
|
|
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
// Fill the filesystem.
|
|
|
|
auto FooCpp = testPath("src/foo.cpp");
|
2018-02-14 01:47:16 +08:00
|
|
|
FS.Files[FooCpp] = "";
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
auto HeaderInPreambleH = testPath("src/header_in_preamble.h");
|
2020-01-29 03:23:46 +08:00
|
|
|
FS.Files[HeaderInPreambleH] = std::string(HeaderInPreambleAnnotations.code());
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
auto HeaderNotInPreambleH = testPath("src/header_not_in_preamble.h");
|
2020-01-29 03:23:46 +08:00
|
|
|
FS.Files[HeaderNotInPreambleH] =
|
|
|
|
std::string(HeaderNotInPreambleAnnotations.code());
|
2018-02-14 01:47:16 +08:00
|
|
|
|
2018-03-06 01:28:54 +08:00
|
|
|
runAddDocument(Server, FooCpp, SourceAnnotations.code());
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
|
|
|
|
// Go to a definition in main source file.
|
2018-02-15 21:15:47 +08:00
|
|
|
auto Locations =
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p1"));
|
2018-02-14 01:47:16 +08:00
|
|
|
EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo", SourceAnnotations.range())));
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
|
|
|
|
// Go to a definition in header_in_preamble.h.
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p2"));
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
*Locations,
|
|
|
|
ElementsAre(Sym("bar_preamble", HeaderInPreambleAnnotations.range())));
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
|
|
|
|
// Go to a definition in header_not_in_preamble.h.
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("p3"));
|
[clangd] Avoid duplicates in findDefinitions response
Summary:
When compile_commands.json contains some source files expressed as
relative paths, we can get duplicate responses to findDefinitions. The
responses only differ by the URI, which are different versions of the
same file:
"result": [
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h"
},
{
...
"uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h"
}
]
In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry
by calling tryGetRealPathName. However, this can fail and return an
empty string. It may be bug a bug in clang, but in any case we should
fall back to computing it ourselves if it happens.
I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we
return right away (a real path is always absolute). Otherwise, we try
to build an absolute path, as we did before, but we also call
VFS->getRealPath to make sure to get the canonical path (e.g. without
any ".." in it).
Reviewers: malaperle
Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits
Differential Revision: https://reviews.llvm.org/D48687
llvm-svn: 339483
2018-08-11 06:27:53 +08:00
|
|
|
EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error";
|
|
|
|
EXPECT_THAT(*Locations,
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
ElementsAre(Sym("bar_not_preamble",
|
|
|
|
HeaderNotInPreambleAnnotations.range())));
|
2018-02-14 01:47:16 +08:00
|
|
|
}
|
|
|
|
|
2018-02-21 10:39:08 +08:00
|
|
|
TEST(GoToInclude, All) {
|
|
|
|
MockFSProvider FS;
|
|
|
|
MockCompilationDatabase CDB;
|
2020-01-24 21:08:56 +08:00
|
|
|
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
2018-02-21 10:39:08 +08:00
|
|
|
|
|
|
|
auto FooCpp = testPath("foo.cpp");
|
|
|
|
const char *SourceContents = R"cpp(
|
|
|
|
#include ^"$2^foo.h$3^"
|
|
|
|
#include "$4^invalid.h"
|
|
|
|
int b = a;
|
|
|
|
// test
|
|
|
|
int foo;
|
|
|
|
#in$5^clude "$6^foo.h"$7^
|
|
|
|
)cpp";
|
|
|
|
Annotations SourceAnnotations(SourceContents);
|
2020-01-29 03:23:46 +08:00
|
|
|
FS.Files[FooCpp] = std::string(SourceAnnotations.code());
|
2018-02-21 10:39:08 +08:00
|
|
|
auto FooH = testPath("foo.h");
|
|
|
|
|
2018-03-13 00:49:24 +08:00
|
|
|
const char *HeaderContents = R"cpp([[]]#pragma once
|
|
|
|
int a;
|
|
|
|
)cpp";
|
2018-02-21 10:39:08 +08:00
|
|
|
Annotations HeaderAnnotations(HeaderContents);
|
2020-01-29 03:23:46 +08:00
|
|
|
FS.Files[FooH] = std::string(HeaderAnnotations.code());
|
2018-02-21 10:39:08 +08:00
|
|
|
|
|
|
|
Server.addDocument(FooH, HeaderAnnotations.code());
|
|
|
|
Server.addDocument(FooCpp, SourceAnnotations.code());
|
|
|
|
|
|
|
|
// Test include in preamble.
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
auto Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point());
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
|
2018-02-21 10:39:08 +08:00
|
|
|
|
|
|
|
// Test include in preamble, last char.
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("2"));
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
|
2018-02-21 10:39:08 +08:00
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("3"));
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
|
2018-02-21 10:39:08 +08:00
|
|
|
|
|
|
|
// Test include outside of preamble.
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("6"));
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
|
2018-02-21 10:39:08 +08:00
|
|
|
|
|
|
|
// Test a few positions that do not result in Locations.
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("4"));
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
2018-03-13 07:22:35 +08:00
|
|
|
EXPECT_THAT(*Locations, IsEmpty());
|
2018-02-21 10:39:08 +08:00
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("5"));
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
|
2018-02-21 10:39:08 +08:00
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
Locations = runLocateSymbolAt(Server, FooCpp, SourceAnnotations.point("7"));
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
2019-04-04 21:09:02 +08:00
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
|
|
|
|
|
|
|
|
// Objective C #import directive.
|
|
|
|
Annotations ObjC(R"objc(
|
|
|
|
#import "^foo.h"
|
|
|
|
)objc");
|
|
|
|
auto FooM = testPath("foo.m");
|
2020-01-29 03:23:46 +08:00
|
|
|
FS.Files[FooM] = std::string(ObjC.code());
|
2019-04-04 21:09:02 +08:00
|
|
|
|
|
|
|
Server.addDocument(FooM, ObjC.code());
|
|
|
|
Locations = runLocateSymbolAt(Server, FooM, ObjC.point());
|
|
|
|
ASSERT_TRUE(bool(Locations)) << "locateSymbolAt returned an error";
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
EXPECT_THAT(*Locations, ElementsAre(Sym("foo.h", HeaderAnnotations.range())));
|
2018-02-21 10:39:08 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
TEST(LocateSymbol, WithPreamble) {
|
2018-08-17 16:15:22 +08:00
|
|
|
// Test stragety: AST should always use the latest preamble instead of last
|
|
|
|
// good preamble.
|
|
|
|
MockFSProvider FS;
|
|
|
|
MockCompilationDatabase CDB;
|
2020-01-24 21:08:56 +08:00
|
|
|
ClangdServer Server(CDB, FS, ClangdServer::optsForTest());
|
2018-08-17 16:15:22 +08:00
|
|
|
|
|
|
|
auto FooCpp = testPath("foo.cpp");
|
|
|
|
// The trigger locations must be the same.
|
|
|
|
Annotations FooWithHeader(R"cpp(#include "fo^o.h")cpp");
|
|
|
|
Annotations FooWithoutHeader(R"cpp(double [[fo^o]]();)cpp");
|
|
|
|
|
2020-01-29 03:23:46 +08:00
|
|
|
FS.Files[FooCpp] = std::string(FooWithHeader.code());
|
2018-08-17 16:15:22 +08:00
|
|
|
|
|
|
|
auto FooH = testPath("foo.h");
|
|
|
|
Annotations FooHeader(R"cpp([[]])cpp");
|
2020-01-29 03:23:46 +08:00
|
|
|
FS.Files[FooH] = std::string(FooHeader.code());
|
2018-08-17 16:15:22 +08:00
|
|
|
|
|
|
|
runAddDocument(Server, FooCpp, FooWithHeader.code());
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
// LocateSymbol goes to a #include file: the result comes from the preamble.
|
2018-08-17 16:15:22 +08:00
|
|
|
EXPECT_THAT(
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
cantFail(runLocateSymbolAt(Server, FooCpp, FooWithHeader.point())),
|
|
|
|
ElementsAre(Sym("foo.h", FooHeader.range())));
|
2018-08-17 16:15:22 +08:00
|
|
|
|
|
|
|
// Only preamble is built, and no AST is built in this request.
|
|
|
|
Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::No);
|
|
|
|
// We build AST here, and it should use the latest preamble rather than the
|
|
|
|
// stale one.
|
|
|
|
EXPECT_THAT(
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
|
|
|
|
ElementsAre(Sym("foo", FooWithoutHeader.range())));
|
2018-08-17 16:15:22 +08:00
|
|
|
|
|
|
|
// Reset test environment.
|
|
|
|
runAddDocument(Server, FooCpp, FooWithHeader.code());
|
|
|
|
// Both preamble and AST are built in this request.
|
|
|
|
Server.addDocument(FooCpp, FooWithoutHeader.code(), WantDiagnostics::Yes);
|
|
|
|
// Use the AST being built in above request.
|
|
|
|
EXPECT_THAT(
|
[clangd] Implement textDocument/declaration from LSP 3.14
Summary:
LSP now reflects the declaration/definition distinction.
Language server changes:
- textDocument/definition now returns a definition if one is found, otherwise
the declaration. It no longer returns declaration + definition if they are
distinct.
- textDocument/declaration returns the best declaration we can find.
- For macros, the active macro definition is returned for both methods.
- For include directive, the top of the target file is returned for both.
There doesn't appear to be a discovery mechanism (we can't return everything to
clients that only know about definition), so this changes existing behavior.
In practice, it should greatly reduce the fraction of the time we need to show
the user a menu of options.
C++ API changes:
- findDefinitions is replaced by locateSymbolAt, which returns a
vector<LocatedSymbol> - one for each symbol under the cursor.
- this contains the preferred declaration, the definition (if found), and
the symbol name
This API enables some potentially-neat extensions, like swapping between decl
and def, and exposing the symbol name to the UI in the case of multiple symbols.
Reviewers: hokein
Subscribers: ilya-biryukov, javed.absar, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D57388
llvm-svn: 352864
2019-02-01 19:26:13 +08:00
|
|
|
cantFail(runLocateSymbolAt(Server, FooCpp, FooWithoutHeader.point())),
|
|
|
|
ElementsAre(Sym("foo", FooWithoutHeader.range())));
|
2018-08-17 16:15:22 +08:00
|
|
|
}
|
|
|
|
|
2018-09-05 18:33:36 +08:00
|
|
|
TEST(FindReferences, WithinAST) {
|
|
|
|
const char *Tests[] = {
|
|
|
|
R"cpp(// Local variable
|
|
|
|
int main() {
|
2018-10-04 17:56:08 +08:00
|
|
|
int [[foo]];
|
|
|
|
[[^foo]] = 2;
|
|
|
|
int test1 = [[foo]];
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Struct
|
|
|
|
namespace ns1 {
|
2018-10-04 17:56:08 +08:00
|
|
|
struct [[Foo]] {};
|
2018-09-05 18:33:36 +08:00
|
|
|
} // namespace ns1
|
|
|
|
int main() {
|
2018-10-04 17:56:08 +08:00
|
|
|
ns1::[[Fo^o]]* Params;
|
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Forward declaration
|
|
|
|
class [[Foo]];
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
Summary:
The historic behavior of TestTU is to gather diagnostics and otherwise ignore
them. So if a test has a syntax error, and doesn't assert diagnostics, it
silently misbehaves.
This can be annoying when developing tests, as evidenced by various tests
gaining "assert no diagnostics" where that's not really the point of the test.
This patch aims to make that default behavior. For the first error
(not warning), TestTU will call ADD_FAILURE().
This can be suppressed with a comment containing "error-ok". For now that will
suppress any errors in the TU. We can make this stricter later -verify style.
(-verify itself is hard to reuse because of DiagnosticConsumer interfaces...)
A magic-comment was chosen over a TestTU option because of table-driven tests.
In addition to the behavior change, this patch:
- adds //error-ok where we're knowingly testing invalid code
(e.g. for diagnostics, crash-resilience, or token-level tests)
- fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;)
- removes a bunch of now-redundant instances of "assert no diagnostics"
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73199
2020-01-22 23:38:41 +08:00
|
|
|
class [[Foo]] {};
|
2018-10-04 17:56:08 +08:00
|
|
|
int main() {
|
|
|
|
[[Fo^o]] foo;
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Function
|
2018-10-04 17:56:08 +08:00
|
|
|
int [[foo]](int) {}
|
2018-09-05 18:33:36 +08:00
|
|
|
int main() {
|
2018-10-04 17:56:08 +08:00
|
|
|
auto *X = &[[^foo]];
|
[clangd] Errors in TestTU cause test failures unless suppressed with error-ok.
Summary:
The historic behavior of TestTU is to gather diagnostics and otherwise ignore
them. So if a test has a syntax error, and doesn't assert diagnostics, it
silently misbehaves.
This can be annoying when developing tests, as evidenced by various tests
gaining "assert no diagnostics" where that's not really the point of the test.
This patch aims to make that default behavior. For the first error
(not warning), TestTU will call ADD_FAILURE().
This can be suppressed with a comment containing "error-ok". For now that will
suppress any errors in the TU. We can make this stricter later -verify style.
(-verify itself is hard to reuse because of DiagnosticConsumer interfaces...)
A magic-comment was chosen over a TestTU option because of table-driven tests.
In addition to the behavior change, this patch:
- adds //error-ok where we're knowingly testing invalid code
(e.g. for diagnostics, crash-resilience, or token-level tests)
- fixes a bunch of errors in the checked-in tests, mostly trivial (missing ;)
- removes a bunch of now-redundant instances of "assert no diagnostics"
Reviewers: kadircet
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D73199
2020-01-22 23:38:41 +08:00
|
|
|
[[foo]](42);
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Field
|
|
|
|
struct Foo {
|
2018-10-04 17:56:08 +08:00
|
|
|
int [[foo]];
|
|
|
|
Foo() : [[foo]](0) {}
|
2018-09-05 18:33:36 +08:00
|
|
|
};
|
|
|
|
int main() {
|
|
|
|
Foo f;
|
2018-10-04 17:56:08 +08:00
|
|
|
f.[[f^oo]] = 1;
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Method call
|
|
|
|
struct Foo { int [[foo]](); };
|
|
|
|
int Foo::[[foo]]() {}
|
|
|
|
int main() {
|
|
|
|
Foo f;
|
2018-10-04 17:56:08 +08:00
|
|
|
f.[[^foo]]();
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
2019-03-08 17:54:37 +08:00
|
|
|
|
|
|
|
R"cpp(// Constructor
|
|
|
|
struct Foo {
|
|
|
|
[[F^oo]](int);
|
|
|
|
};
|
|
|
|
void foo() {
|
|
|
|
Foo f = [[Foo]](42);
|
|
|
|
}
|
|
|
|
)cpp",
|
2018-09-05 18:33:36 +08:00
|
|
|
|
|
|
|
R"cpp(// Typedef
|
2018-10-04 17:56:08 +08:00
|
|
|
typedef int [[Foo]];
|
2018-09-05 18:33:36 +08:00
|
|
|
int main() {
|
2018-10-04 17:56:08 +08:00
|
|
|
[[^Foo]] bar;
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(// Namespace
|
2018-10-04 17:56:08 +08:00
|
|
|
namespace [[ns]] {
|
2018-09-05 18:33:36 +08:00
|
|
|
struct Foo {};
|
|
|
|
} // namespace ns
|
2018-10-04 17:56:08 +08:00
|
|
|
int main() { [[^ns]]::Foo foo; }
|
2018-09-05 18:33:36 +08:00
|
|
|
)cpp",
|
[clangd] Use expansion location when the ref is inside macros.
Summary:
Previously, xrefs has inconsistent behavior when the reference is inside
macro body:
- AST-based xrefs (for main file) uses the expansion location;
- our index uses the spelling location;
This patch makes our index use file locations for references, which is
consistent with AST-based xrefs, and kythe as well.
After this patch, memory usage of static index on LLVM increases ~5%.
Reviewers: ilya-biryukov
Subscribers: merge_guards_bot, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D70480
2019-12-09 19:00:42 +08:00
|
|
|
|
|
|
|
R"cpp(// Macros
|
|
|
|
#define TYPE(X) X
|
|
|
|
#define FOO Foo
|
|
|
|
#define CAT(X, Y) X##Y
|
|
|
|
class [[Fo^o]] {};
|
|
|
|
void test() {
|
|
|
|
TYPE([[Foo]]) foo;
|
|
|
|
[[FOO]] foo2;
|
|
|
|
TYPE(TYPE([[Foo]])) foo3;
|
|
|
|
[[CAT]](Fo, o) foo4;
|
|
|
|
}
|
|
|
|
)cpp",
|
2020-01-08 20:57:00 +08:00
|
|
|
|
|
|
|
R"cpp(// Macros
|
|
|
|
#define [[MA^CRO]](X) (X+1)
|
|
|
|
void test() {
|
|
|
|
int x = [[MACRO]]([[MACRO]](1));
|
|
|
|
}
|
|
|
|
)cpp",
|
2020-02-12 21:42:18 +08:00
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
int [[v^ar]] = 0;
|
|
|
|
void foo(int s = [[var]]);
|
|
|
|
)cpp",
|
2020-02-19 19:27:12 +08:00
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
class [[Fo^o]] {};
|
|
|
|
void func([[Foo]]<int>);
|
|
|
|
)cpp",
|
2020-02-20 22:22:07 +08:00
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
template <typename T>
|
|
|
|
class [[Foo]] {};
|
|
|
|
void func([[Fo^o]]<int>);
|
|
|
|
)cpp",
|
2018-09-05 18:33:36 +08:00
|
|
|
};
|
|
|
|
for (const char *Test : Tests) {
|
|
|
|
Annotations T(Test);
|
|
|
|
auto AST = TestTU::withCode(T.code()).build();
|
|
|
|
std::vector<Matcher<Location>> ExpectedLocations;
|
2018-10-04 17:56:08 +08:00
|
|
|
for (const auto &R : T.ranges())
|
2018-09-05 18:33:36 +08:00
|
|
|
ExpectedLocations.push_back(RangeIs(R));
|
2019-11-18 18:35:00 +08:00
|
|
|
EXPECT_THAT(findReferences(AST, T.point(), 0).References,
|
2018-09-05 18:33:36 +08:00
|
|
|
ElementsAreArray(ExpectedLocations))
|
|
|
|
<< Test;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-13 21:17:04 +08:00
|
|
|
TEST(FindReferences, ExplicitSymbols) {
|
|
|
|
const char *Tests[] = {
|
|
|
|
R"cpp(
|
2019-08-20 22:07:27 +08:00
|
|
|
struct Foo { Foo* [[self]]() const; };
|
2018-12-13 21:17:04 +08:00
|
|
|
void f() {
|
2019-08-20 22:07:27 +08:00
|
|
|
Foo foo;
|
|
|
|
if (Foo* T = foo.[[^self]]()) {} // Foo member call expr.
|
2018-12-13 21:17:04 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
struct Foo { Foo(int); };
|
|
|
|
Foo f() {
|
2019-08-20 22:07:27 +08:00
|
|
|
int [[b]];
|
|
|
|
return [[^b]]; // Foo constructor expr.
|
2018-12-13 21:17:04 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
struct Foo {};
|
|
|
|
void g(Foo);
|
2019-08-20 22:07:27 +08:00
|
|
|
Foo [[f]]();
|
2018-12-13 21:17:04 +08:00
|
|
|
void call() {
|
2019-08-20 22:07:27 +08:00
|
|
|
g([[^f]]()); // Foo constructor expr.
|
2018-12-13 21:17:04 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
|
|
|
|
|
|
|
R"cpp(
|
2019-08-20 22:07:27 +08:00
|
|
|
void [[foo]](int);
|
|
|
|
void [[foo]](double);
|
2018-12-13 21:17:04 +08:00
|
|
|
|
|
|
|
namespace ns {
|
2019-08-20 22:07:27 +08:00
|
|
|
using ::[[fo^o]];
|
2018-12-13 21:17:04 +08:00
|
|
|
}
|
|
|
|
)cpp",
|
2019-08-21 18:54:19 +08:00
|
|
|
|
|
|
|
R"cpp(
|
|
|
|
struct X {
|
|
|
|
operator bool();
|
|
|
|
};
|
|
|
|
|
|
|
|
int test() {
|
|
|
|
X [[a]];
|
|
|
|
[[a]].operator bool();
|
|
|
|
if ([[a^]]) {} // ignore implicit conversion-operator AST node
|
|
|
|
}
|
|
|
|
)cpp",
|
2018-12-13 21:17:04 +08:00
|
|
|
};
|
|
|
|
for (const char *Test : Tests) {
|
|
|
|
Annotations T(Test);
|
|
|
|
auto AST = TestTU::withCode(T.code()).build();
|
|
|
|
std::vector<Matcher<Location>> ExpectedLocations;
|
|
|
|
for (const auto &R : T.ranges())
|
|
|
|
ExpectedLocations.push_back(RangeIs(R));
|
2019-08-20 22:07:27 +08:00
|
|
|
ASSERT_THAT(ExpectedLocations, Not(IsEmpty()));
|
2019-11-18 18:35:00 +08:00
|
|
|
EXPECT_THAT(findReferences(AST, T.point(), 0).References,
|
2018-12-13 21:17:04 +08:00
|
|
|
ElementsAreArray(ExpectedLocations))
|
|
|
|
<< Test;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-08 20:57:00 +08:00
|
|
|
TEST(FindReferences, NeedsIndexForSymbols) {
|
2018-09-05 18:33:36 +08:00
|
|
|
const char *Header = "int foo();";
|
|
|
|
Annotations Main("int main() { [[f^oo]](); }");
|
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.Code = std::string(Main.code());
|
2018-09-05 18:33:36 +08:00
|
|
|
TU.HeaderCode = Header;
|
|
|
|
auto AST = TU.build();
|
|
|
|
|
|
|
|
// References in main file are returned without index.
|
2019-11-18 18:35:00 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
|
|
|
|
ElementsAre(RangeIs(Main.range())));
|
2018-09-05 18:33:36 +08:00
|
|
|
Annotations IndexedMain(R"cpp(
|
|
|
|
int main() { [[f^oo]](); }
|
|
|
|
)cpp");
|
|
|
|
|
|
|
|
// References from indexed files are included.
|
|
|
|
TestTU IndexedTU;
|
2020-01-29 03:23:46 +08:00
|
|
|
IndexedTU.Code = std::string(IndexedMain.code());
|
2018-09-05 18:33:36 +08:00
|
|
|
IndexedTU.Filename = "Indexed.cpp";
|
|
|
|
IndexedTU.HeaderCode = Header;
|
2019-11-18 18:35:00 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
|
|
|
|
ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
|
|
|
|
auto LimitRefs =
|
|
|
|
findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
|
|
|
|
EXPECT_EQ(1u, LimitRefs.References.size());
|
|
|
|
EXPECT_TRUE(LimitRefs.HasMore);
|
2019-01-15 02:11:09 +08:00
|
|
|
|
2020-01-08 20:57:00 +08:00
|
|
|
// Avoid indexed results for the main file. Use AST for the mainfile.
|
2018-09-05 18:33:36 +08:00
|
|
|
TU.Code = ("\n\n" + Main.code()).str();
|
2019-11-18 18:35:00 +08:00
|
|
|
EXPECT_THAT(findReferences(AST, Main.point(), 0, TU.index().get()).References,
|
2018-09-05 18:33:36 +08:00
|
|
|
ElementsAre(RangeIs(Main.range())));
|
2018-09-11 21:01:49 +08:00
|
|
|
}
|
2018-09-05 18:33:36 +08:00
|
|
|
|
2020-01-08 20:57:00 +08:00
|
|
|
TEST(FindReferences, NeedsIndexForMacro) {
|
|
|
|
const char *Header = "#define MACRO(X) (X+1)";
|
|
|
|
Annotations Main(R"cpp(
|
|
|
|
int main() {
|
|
|
|
int a = [[MA^CRO]](1);
|
|
|
|
}
|
|
|
|
)cpp");
|
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.Code = std::string(Main.code());
|
2020-01-08 20:57:00 +08:00
|
|
|
TU.HeaderCode = Header;
|
|
|
|
auto AST = TU.build();
|
|
|
|
|
|
|
|
// References in main file are returned without index.
|
|
|
|
EXPECT_THAT(
|
|
|
|
findReferences(AST, Main.point(), 0, /*Index=*/nullptr).References,
|
|
|
|
ElementsAre(RangeIs(Main.range())));
|
|
|
|
|
|
|
|
Annotations IndexedMain(R"cpp(
|
|
|
|
int indexed_main() {
|
|
|
|
int a = [[MACRO]](1);
|
|
|
|
}
|
|
|
|
)cpp");
|
|
|
|
|
|
|
|
// References from indexed files are included.
|
|
|
|
TestTU IndexedTU;
|
2020-01-29 03:23:46 +08:00
|
|
|
IndexedTU.Code = std::string(IndexedMain.code());
|
2020-01-08 20:57:00 +08:00
|
|
|
IndexedTU.Filename = "Indexed.cpp";
|
|
|
|
IndexedTU.HeaderCode = Header;
|
|
|
|
EXPECT_THAT(
|
|
|
|
findReferences(AST, Main.point(), 0, IndexedTU.index().get()).References,
|
|
|
|
ElementsAre(RangeIs(Main.range()), RangeIs(IndexedMain.range())));
|
|
|
|
auto LimitRefs =
|
|
|
|
findReferences(AST, Main.point(), /*Limit*/ 1, IndexedTU.index().get());
|
|
|
|
EXPECT_EQ(1u, LimitRefs.References.size());
|
|
|
|
EXPECT_TRUE(LimitRefs.HasMore);
|
|
|
|
}
|
|
|
|
|
2018-09-05 18:33:36 +08:00
|
|
|
TEST(FindReferences, NoQueryForLocalSymbols) {
|
|
|
|
struct RecordingIndex : public MemIndex {
|
2019-01-07 23:45:19 +08:00
|
|
|
mutable Optional<llvm::DenseSet<SymbolID>> RefIDs;
|
2019-11-13 21:42:26 +08:00
|
|
|
bool refs(const RefsRequest &Req,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::function_ref<void(const Ref &)>) const override {
|
2018-09-05 18:33:36 +08:00
|
|
|
RefIDs = Req.IDs;
|
2019-11-13 21:42:26 +08:00
|
|
|
return false;
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Test {
|
|
|
|
StringRef AnnotatedCode;
|
|
|
|
bool WantQuery;
|
|
|
|
} Tests[] = {
|
|
|
|
{"int ^x;", true},
|
|
|
|
// For now we don't assume header structure which would allow skipping.
|
|
|
|
{"namespace { int ^x; }", true},
|
|
|
|
{"static int ^x;", true},
|
|
|
|
// Anything in a function certainly can't be referenced though.
|
|
|
|
{"void foo() { int ^x; }", false},
|
|
|
|
{"void foo() { struct ^x{}; }", false},
|
|
|
|
{"auto lambda = []{ int ^x; };", false},
|
|
|
|
};
|
|
|
|
for (Test T : Tests) {
|
|
|
|
Annotations File(T.AnnotatedCode);
|
|
|
|
RecordingIndex Rec;
|
|
|
|
auto AST = TestTU::withCode(File.code()).build();
|
2019-01-15 02:11:09 +08:00
|
|
|
findReferences(AST, File.point(), 0, &Rec);
|
2018-09-05 18:33:36 +08:00
|
|
|
if (T.WantQuery)
|
2018-10-20 23:30:37 +08:00
|
|
|
EXPECT_NE(Rec.RefIDs, None) << T.AnnotatedCode;
|
2018-09-05 18:33:36 +08:00
|
|
|
else
|
2018-10-20 23:30:37 +08:00
|
|
|
EXPECT_EQ(Rec.RefIDs, None) << T.AnnotatedCode;
|
2018-09-05 18:33:36 +08:00
|
|
|
}
|
2018-09-11 21:01:49 +08:00
|
|
|
}
|
2018-09-05 18:33:36 +08:00
|
|
|
|
2019-09-26 15:27:43 +08:00
|
|
|
TEST(GetNonLocalDeclRefs, All) {
|
|
|
|
struct Case {
|
|
|
|
llvm::StringRef AnnotatedCode;
|
2020-01-29 06:30:02 +08:00
|
|
|
std::vector<std::string> ExpectedDecls;
|
2019-09-26 15:27:43 +08:00
|
|
|
} Cases[] = {
|
|
|
|
{
|
|
|
|
// VarDecl and ParamVarDecl
|
|
|
|
R"cpp(
|
|
|
|
void bar();
|
|
|
|
void ^foo(int baz) {
|
|
|
|
int x = 10;
|
|
|
|
bar();
|
|
|
|
})cpp",
|
|
|
|
{"bar"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Method from class
|
|
|
|
R"cpp(
|
|
|
|
class Foo { public: void foo(); };
|
|
|
|
class Bar {
|
|
|
|
void foo();
|
|
|
|
void bar();
|
|
|
|
};
|
|
|
|
void Bar::^foo() {
|
|
|
|
Foo f;
|
|
|
|
bar();
|
|
|
|
f.foo();
|
|
|
|
})cpp",
|
|
|
|
{"Bar", "Bar::bar", "Foo", "Foo::foo"},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Local types
|
|
|
|
R"cpp(
|
|
|
|
void ^foo() {
|
|
|
|
class Foo { public: void foo() {} };
|
|
|
|
class Bar { public: void bar() {} };
|
|
|
|
Foo f;
|
|
|
|
Bar b;
|
|
|
|
b.bar();
|
|
|
|
f.foo();
|
|
|
|
})cpp",
|
|
|
|
{},
|
|
|
|
},
|
|
|
|
{
|
|
|
|
// Template params
|
|
|
|
R"cpp(
|
|
|
|
template <typename T, template<typename> class Q>
|
|
|
|
void ^foo() {
|
|
|
|
T x;
|
|
|
|
Q<T> y;
|
|
|
|
})cpp",
|
|
|
|
{},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
for (const Case &C : Cases) {
|
|
|
|
Annotations File(C.AnnotatedCode);
|
|
|
|
auto AST = TestTU::withCode(File.code()).build();
|
|
|
|
SourceLocation SL = llvm::cantFail(
|
|
|
|
sourceLocationInMainFile(AST.getSourceManager(), File.point()));
|
|
|
|
|
|
|
|
const FunctionDecl *FD =
|
|
|
|
llvm::dyn_cast<FunctionDecl>(&findDecl(AST, [SL](const NamedDecl &ND) {
|
|
|
|
return ND.getLocation() == SL && llvm::isa<FunctionDecl>(ND);
|
|
|
|
}));
|
|
|
|
ASSERT_NE(FD, nullptr);
|
|
|
|
|
|
|
|
auto NonLocalDeclRefs = getNonLocalDeclRefs(AST, FD);
|
|
|
|
std::vector<std::string> Names;
|
|
|
|
for (const Decl *D : NonLocalDeclRefs) {
|
|
|
|
if (const auto *ND = llvm::dyn_cast<NamedDecl>(D))
|
|
|
|
Names.push_back(ND->getQualifiedNameAsString());
|
|
|
|
}
|
2019-10-18 20:07:19 +08:00
|
|
|
EXPECT_THAT(Names, UnorderedElementsAreArray(C.ExpectedDecls))
|
|
|
|
<< File.code();
|
2019-09-26 15:27:43 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-17 02:08:51 +08:00
|
|
|
TEST(DocumentLinks, All) {
|
|
|
|
Annotations MainCpp(R"cpp(
|
|
|
|
#include $foo[["foo.h"]]
|
|
|
|
int end_of_preamble = 0;
|
|
|
|
#include $bar[["bar.h"]]
|
|
|
|
)cpp");
|
|
|
|
|
|
|
|
TestTU TU;
|
2020-01-29 03:23:46 +08:00
|
|
|
TU.Code = std::string(MainCpp.code());
|
2019-12-17 02:08:51 +08:00
|
|
|
TU.AdditionalFiles = {{"foo.h", ""}, {"bar.h", ""}};
|
|
|
|
auto AST = TU.build();
|
|
|
|
|
|
|
|
EXPECT_THAT(
|
|
|
|
clangd::getDocumentLinks(AST),
|
|
|
|
ElementsAre(
|
|
|
|
DocumentLink({MainCpp.range("foo"),
|
|
|
|
URIForFile::canonicalize(testPath("foo.h"), "")}),
|
|
|
|
DocumentLink({MainCpp.range("bar"),
|
|
|
|
URIForFile::canonicalize(testPath("bar.h"), "")})));
|
|
|
|
}
|
|
|
|
|
2017-12-21 00:06:05 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|