[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
//===-- SymbolCollectorTests.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
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-01-31 20:56:51 +08:00
|
|
|
#include "Annotations.h"
|
2018-01-30 06:28:08 +08:00
|
|
|
#include "TestFS.h"
|
2018-06-21 20:12:26 +08:00
|
|
|
#include "TestTU.h"
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
#include "index/SymbolCollector.h"
|
|
|
|
#include "clang/Basic/FileManager.h"
|
|
|
|
#include "clang/Basic/FileSystemOptions.h"
|
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
2017-12-13 20:53:16 +08:00
|
|
|
#include "clang/Index/IndexingAction.h"
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
#include "clang/Tooling/Tooling.h"
|
|
|
|
#include "llvm/ADT/IntrusiveRefCntPtr.h"
|
|
|
|
#include "llvm/ADT/STLExtras.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
|
|
|
#include "llvm/Support/MemoryBuffer.h"
|
2018-10-10 21:27:25 +08:00
|
|
|
#include "llvm/Support/VirtualFileSystem.h"
|
2019-05-03 21:17:29 +08:00
|
|
|
#include "gmock/gmock-matchers.h"
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
#include "gmock/gmock-more-matchers.h"
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
#include "gmock/gmock.h"
|
2017-12-13 20:53:16 +08:00
|
|
|
#include "gtest/gtest.h"
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
|
2018-08-31 20:54:13 +08:00
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
namespace {
|
|
|
|
|
2019-05-06 18:08:47 +08:00
|
|
|
using ::testing::_;
|
|
|
|
using ::testing::AllOf;
|
|
|
|
using ::testing::Contains;
|
|
|
|
using ::testing::Each;
|
|
|
|
using ::testing::ElementsAre;
|
|
|
|
using ::testing::Field;
|
|
|
|
using ::testing::Not;
|
|
|
|
using ::testing::Pair;
|
|
|
|
using ::testing::UnorderedElementsAre;
|
|
|
|
using ::testing::UnorderedElementsAreArray;
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
|
|
|
|
// GMock helpers for matching Symbol.
|
2018-06-23 00:11:35 +08:00
|
|
|
MATCHER_P(Labeled, Label, "") {
|
|
|
|
return (arg.Name + arg.Signature).str() == Label;
|
|
|
|
}
|
2018-08-31 21:55:01 +08:00
|
|
|
MATCHER_P(ReturnType, D, "") { return arg.ReturnType == D; }
|
|
|
|
MATCHER_P(Doc, D, "") { return arg.Documentation == D; }
|
2018-01-10 01:32:00 +08:00
|
|
|
MATCHER_P(Snippet, S, "") {
|
2018-06-23 00:11:35 +08:00
|
|
|
return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
|
2018-01-10 01:32:00 +08:00
|
|
|
}
|
2018-01-20 06:18:21 +08:00
|
|
|
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
|
2019-04-12 18:09:24 +08:00
|
|
|
MATCHER_P(TemplateArgs, TemplArgs, "") {
|
|
|
|
return arg.TemplateSpecializationArgs == TemplArgs;
|
|
|
|
}
|
2018-11-14 19:55:45 +08:00
|
|
|
MATCHER_P(DeclURI, P, "") {
|
|
|
|
return StringRef(arg.CanonicalDeclaration.FileURI) == P;
|
|
|
|
}
|
|
|
|
MATCHER_P(DefURI, P, "") { return StringRef(arg.Definition.FileURI) == P; }
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
MATCHER(IncludeHeader, "") { return !arg.IncludeHeaders.empty(); }
|
[clangd] Support multiple #include headers in one symbol.
Summary:
Currently, a symbol can have only one #include header attached, which
might not work well if the symbol can be imported via different #includes depending
on where it's used. This patch stores multiple #include headers (with # references)
for each symbol, so that CodeCompletion can decide which include to insert.
In this patch, code completion simply picks the most popular include as the default inserted header. We also return all possible includes and their edits in the `CodeCompletion` results.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: mgrang, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51291
llvm-svn: 341304
2018-09-03 18:18:21 +08:00
|
|
|
MATCHER_P(IncludeHeader, P, "") {
|
|
|
|
return (arg.IncludeHeaders.size() == 1) &&
|
|
|
|
(arg.IncludeHeaders.begin()->IncludeHeader == P);
|
|
|
|
}
|
2019-01-03 21:28:05 +08:00
|
|
|
MATCHER_P2(IncludeHeaderWithRef, IncludeHeader, References, "") {
|
[clangd] Support multiple #include headers in one symbol.
Summary:
Currently, a symbol can have only one #include header attached, which
might not work well if the symbol can be imported via different #includes depending
on where it's used. This patch stores multiple #include headers (with # references)
for each symbol, so that CodeCompletion can decide which include to insert.
In this patch, code completion simply picks the most popular include as the default inserted header. We also return all possible includes and their edits in the `CodeCompletion` results.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: mgrang, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51291
llvm-svn: 341304
2018-09-03 18:18:21 +08:00
|
|
|
return (arg.IncludeHeader == IncludeHeader) && (arg.References == References);
|
|
|
|
}
|
2018-04-13 16:30:39 +08:00
|
|
|
MATCHER_P(DeclRange, Pos, "") {
|
[clangd] Encode Line/Column as a 32-bits integer.
Summary:
This would buy us more memory. Using a 32-bits integer is enough for
most human-readable source code (up to 4M lines and 4K columns).
Previsouly, we used 8 bytes for a position, now 4 bytes, it would save
us 8 bytes for each Ref and each Symbol instance.
For LLVM-project binary index file, we save ~13% memory.
| Before | After |
| 412MB | 355MB |
Reviewers: sammccall
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53363
llvm-svn: 344735
2018-10-18 18:43:50 +08:00
|
|
|
return std::make_tuple(arg.CanonicalDeclaration.Start.line(),
|
|
|
|
arg.CanonicalDeclaration.Start.column(),
|
|
|
|
arg.CanonicalDeclaration.End.line(),
|
|
|
|
arg.CanonicalDeclaration.End.column()) ==
|
|
|
|
std::make_tuple(Pos.start.line, Pos.start.character, Pos.end.line,
|
|
|
|
Pos.end.character);
|
2018-04-13 16:30:39 +08:00
|
|
|
}
|
|
|
|
MATCHER_P(DefRange, Pos, "") {
|
[clangd] Encode Line/Column as a 32-bits integer.
Summary:
This would buy us more memory. Using a 32-bits integer is enough for
most human-readable source code (up to 4M lines and 4K columns).
Previsouly, we used 8 bytes for a position, now 4 bytes, it would save
us 8 bytes for each Ref and each Symbol instance.
For LLVM-project binary index file, we save ~13% memory.
| Before | After |
| 412MB | 355MB |
Reviewers: sammccall
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53363
llvm-svn: 344735
2018-10-18 18:43:50 +08:00
|
|
|
return std::make_tuple(
|
|
|
|
arg.Definition.Start.line(), arg.Definition.Start.column(),
|
|
|
|
arg.Definition.End.line(), arg.Definition.End.column()) ==
|
|
|
|
std::make_tuple(Pos.start.line, Pos.start.character, Pos.end.line,
|
|
|
|
Pos.end.character);
|
2018-02-09 22:42:01 +08:00
|
|
|
}
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
MATCHER_P(RefCount, R, "") { return int(arg.References) == R; }
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
MATCHER_P(ForCodeCompletion, IsIndexedForCodeCompletion, "") {
|
2018-09-07 02:52:26 +08:00
|
|
|
return static_cast<bool>(arg.Flags & Symbol::IndexedForCodeCompletion) ==
|
|
|
|
IsIndexedForCodeCompletion;
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
}
|
2018-09-07 02:52:26 +08:00
|
|
|
MATCHER(Deprecated, "") { return arg.Flags & Symbol::Deprecated; }
|
2018-10-18 20:23:05 +08:00
|
|
|
MATCHER(ImplementationDetail, "") {
|
|
|
|
return arg.Flags & Symbol::ImplementationDetail;
|
|
|
|
}
|
2019-01-14 18:01:17 +08:00
|
|
|
MATCHER(VisibleOutsideFile, "") {
|
|
|
|
return static_cast<bool>(arg.Flags & Symbol::VisibleOutsideFile);
|
|
|
|
}
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
MATCHER(RefRange, "") {
|
2019-05-06 18:08:47 +08:00
|
|
|
const Ref &Pos = ::testing::get<0>(arg);
|
|
|
|
const Range &Range = ::testing::get<1>(arg);
|
[clangd] Encode Line/Column as a 32-bits integer.
Summary:
This would buy us more memory. Using a 32-bits integer is enough for
most human-readable source code (up to 4M lines and 4K columns).
Previsouly, we used 8 bytes for a position, now 4 bytes, it would save
us 8 bytes for each Ref and each Symbol instance.
For LLVM-project binary index file, we save ~13% memory.
| Before | After |
| 412MB | 355MB |
Reviewers: sammccall
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D53363
llvm-svn: 344735
2018-10-18 18:43:50 +08:00
|
|
|
return std::make_tuple(Pos.Location.Start.line(), Pos.Location.Start.column(),
|
|
|
|
Pos.Location.End.line(), Pos.Location.End.column()) ==
|
|
|
|
std::make_tuple(Range.start.line, Range.start.character,
|
|
|
|
Range.end.line, Range.end.character);
|
2018-08-31 20:54:13 +08:00
|
|
|
}
|
2019-05-06 18:08:47 +08:00
|
|
|
::testing::Matcher<const std::vector<Ref> &>
|
2018-08-31 20:54:13 +08:00
|
|
|
HaveRanges(const std::vector<Range> Ranges) {
|
2019-05-06 18:08:47 +08:00
|
|
|
return ::testing::UnorderedPointwise(RefRange(), Ranges);
|
2018-08-31 20:54:13 +08:00
|
|
|
}
|
2018-06-21 20:12:26 +08:00
|
|
|
|
|
|
|
class ShouldCollectSymbolTest : public ::testing::Test {
|
|
|
|
public:
|
2019-01-07 23:45:19 +08:00
|
|
|
void build(llvm::StringRef HeaderCode, llvm::StringRef Code = "") {
|
2018-06-21 20:12:26 +08:00
|
|
|
File.HeaderFilename = HeaderName;
|
|
|
|
File.Filename = FileName;
|
|
|
|
File.HeaderCode = HeaderCode;
|
|
|
|
File.Code = Code;
|
|
|
|
AST = File.build();
|
|
|
|
}
|
|
|
|
|
|
|
|
// build() must have been called.
|
2019-01-07 23:45:19 +08:00
|
|
|
bool shouldCollect(llvm::StringRef Name, bool Qualified = true) {
|
2018-06-21 20:12:26 +08:00
|
|
|
assert(AST.hasValue());
|
2019-05-06 18:08:47 +08:00
|
|
|
const NamedDecl &ND =
|
|
|
|
Qualified ? findDecl(*AST, Name) : findUnqualifiedDecl(*AST, Name);
|
2019-06-04 12:25:44 +08:00
|
|
|
const SourceManager &SM = AST->getSourceManager();
|
|
|
|
bool MainFile =
|
|
|
|
SM.isWrittenInMainFile(SM.getExpansionLoc(ND.getBeginLoc()));
|
2018-06-21 20:12:26 +08:00
|
|
|
return SymbolCollector::shouldCollectSymbol(
|
2019-05-29 05:52:34 +08:00
|
|
|
ND, AST->getASTContext(), SymbolCollector::Options(), MainFile);
|
2018-06-21 20:12:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
std::string HeaderName = "f.h";
|
|
|
|
std::string FileName = "f.cpp";
|
|
|
|
TestTU File;
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::Optional<ParsedAST> AST; // Initialized after build.
|
2018-06-21 20:12:26 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(ShouldCollectSymbolTest, ShouldCollectSymbol) {
|
|
|
|
build(R"(
|
|
|
|
namespace nx {
|
2018-11-09 20:56:49 +08:00
|
|
|
class X{};
|
|
|
|
auto f() { int Local; } // auto ensures function body is parsed.
|
2018-12-21 17:32:49 +08:00
|
|
|
struct { int x; } var;
|
2018-06-21 20:12:26 +08:00
|
|
|
}
|
|
|
|
)",
|
2019-01-14 18:01:17 +08:00
|
|
|
R"(
|
|
|
|
class InMain {};
|
|
|
|
namespace { class InAnonymous {}; }
|
|
|
|
static void g();
|
|
|
|
)");
|
2018-06-21 20:12:26 +08:00
|
|
|
auto AST = File.build();
|
|
|
|
EXPECT_TRUE(shouldCollect("nx"));
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::X"));
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::f"));
|
2019-01-14 18:01:17 +08:00
|
|
|
EXPECT_TRUE(shouldCollect("InMain"));
|
|
|
|
EXPECT_TRUE(shouldCollect("InAnonymous", /*Qualified=*/false));
|
|
|
|
EXPECT_TRUE(shouldCollect("g"));
|
2018-06-21 20:12:26 +08:00
|
|
|
|
|
|
|
EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ShouldCollectSymbolTest, NoPrivateProtoSymbol) {
|
|
|
|
HeaderName = "f.proto.h";
|
|
|
|
build(
|
|
|
|
R"(// Generated by the protocol buffer compiler. DO NOT EDIT!
|
|
|
|
namespace nx {
|
|
|
|
class Top_Level {};
|
|
|
|
class TopLevel {};
|
|
|
|
enum Kind {
|
|
|
|
KIND_OK,
|
|
|
|
Kind_Not_Ok,
|
|
|
|
};
|
|
|
|
})");
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::TopLevel"));
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::Kind::KIND_OK"));
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::Kind"));
|
|
|
|
|
|
|
|
EXPECT_FALSE(shouldCollect("nx::Top_Level"));
|
|
|
|
EXPECT_FALSE(shouldCollect("nx::Kind::Kind_Not_Ok"));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(ShouldCollectSymbolTest, DoubleCheckProtoHeaderComment) {
|
|
|
|
HeaderName = "f.proto.h";
|
|
|
|
build(R"(
|
|
|
|
namespace nx {
|
|
|
|
class Top_Level {};
|
|
|
|
enum Kind {
|
|
|
|
Kind_Fine
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)");
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::Top_Level"));
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::Kind_Fine"));
|
|
|
|
}
|
|
|
|
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
class SymbolIndexActionFactory : public tooling::FrontendActionFactory {
|
2017-12-13 20:53:16 +08:00
|
|
|
public:
|
2018-02-16 22:15:55 +08:00
|
|
|
SymbolIndexActionFactory(SymbolCollector::Options COpts,
|
|
|
|
CommentHandler *PragmaHandler)
|
|
|
|
: COpts(std::move(COpts)), PragmaHandler(PragmaHandler) {}
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
|
2018-02-27 23:54:41 +08:00
|
|
|
clang::FrontendAction *create() override {
|
2018-02-16 22:15:55 +08:00
|
|
|
class WrappedIndexAction : public WrapperFrontendAction {
|
|
|
|
public:
|
|
|
|
WrappedIndexAction(std::shared_ptr<SymbolCollector> C,
|
|
|
|
const index::IndexingOptions &Opts,
|
|
|
|
CommentHandler *PragmaHandler)
|
|
|
|
: WrapperFrontendAction(
|
|
|
|
index::createIndexingAction(C, Opts, nullptr)),
|
|
|
|
PragmaHandler(PragmaHandler) {}
|
|
|
|
|
|
|
|
std::unique_ptr<ASTConsumer>
|
2019-01-07 23:45:19 +08:00
|
|
|
CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile) override {
|
2018-02-16 22:15:55 +08:00
|
|
|
if (PragmaHandler)
|
|
|
|
CI.getPreprocessor().addCommentHandler(PragmaHandler);
|
|
|
|
return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
|
|
|
|
}
|
|
|
|
|
2019-02-26 00:00:00 +08:00
|
|
|
bool BeginInvocation(CompilerInstance &CI) override {
|
|
|
|
// Make the compiler parse all comments.
|
|
|
|
CI.getLangOpts().CommentOpts.ParseAllComments = true;
|
|
|
|
return WrapperFrontendAction::BeginInvocation(CI);
|
|
|
|
}
|
|
|
|
|
2018-02-16 22:15:55 +08:00
|
|
|
private:
|
|
|
|
index::IndexingOptions IndexOpts;
|
|
|
|
CommentHandler *PragmaHandler;
|
|
|
|
};
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
index::IndexingOptions IndexOpts;
|
|
|
|
IndexOpts.SystemSymbolFilter =
|
|
|
|
index::IndexingOptions::SystemSymbolFilterKind::All;
|
|
|
|
IndexOpts.IndexFunctionLocals = false;
|
2018-01-10 22:57:58 +08:00
|
|
|
Collector = std::make_shared<SymbolCollector>(COpts);
|
2018-02-27 23:54:41 +08:00
|
|
|
return new WrappedIndexAction(Collector, std::move(IndexOpts),
|
|
|
|
PragmaHandler);
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<SymbolCollector> Collector;
|
2018-01-10 22:57:58 +08:00
|
|
|
SymbolCollector::Options COpts;
|
2018-02-16 22:15:55 +08:00
|
|
|
CommentHandler *PragmaHandler;
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class SymbolCollectorTest : public ::testing::Test {
|
|
|
|
public:
|
2018-02-07 00:10:35 +08:00
|
|
|
SymbolCollectorTest()
|
2019-01-07 23:45:19 +08:00
|
|
|
: InMemoryFileSystem(new llvm::vfs::InMemoryFileSystem),
|
2018-02-16 22:15:55 +08:00
|
|
|
TestHeaderName(testPath("symbol.h")),
|
2018-02-16 17:41:43 +08:00
|
|
|
TestFileName(testPath("symbol.cc")) {
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
TestHeaderURI = URI::create(TestHeaderName).toString();
|
|
|
|
TestFileURI = URI::create(TestFileName).toString();
|
2018-02-07 00:10:35 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
// Note that unlike TestTU, no automatic header guard is added.
|
|
|
|
// HeaderCode should start with #pragma once to be treated as modular.
|
2019-01-07 23:45:19 +08:00
|
|
|
bool runSymbolCollector(llvm::StringRef HeaderCode, llvm::StringRef MainCode,
|
2018-02-06 17:50:35 +08:00
|
|
|
const std::vector<std::string> &ExtraArgs = {}) {
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::IntrusiveRefCntPtr<FileManager> Files(
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
new FileManager(FileSystemOptions(), InMemoryFileSystem));
|
|
|
|
|
2018-02-16 22:15:55 +08:00
|
|
|
auto Factory = llvm::make_unique<SymbolIndexActionFactory>(
|
|
|
|
CollectorOpts, PragmaHandler.get());
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
|
2019-04-11 00:26:58 +08:00
|
|
|
std::vector<std::string> Args = {"symbol_collector", "-fsyntax-only",
|
|
|
|
"-xc++", "-include", TestHeaderName};
|
2018-02-06 17:50:35 +08:00
|
|
|
Args.insert(Args.end(), ExtraArgs.begin(), ExtraArgs.end());
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
// This allows to override the "-xc++" with something else, i.e.
|
|
|
|
// -xobjective-c++.
|
|
|
|
Args.push_back(TestFileName);
|
|
|
|
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
tooling::ToolInvocation Invocation(
|
2019-01-03 21:28:05 +08:00
|
|
|
Args, Factory->create(), Files.get(),
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
std::make_shared<PCHContainerOperations>());
|
|
|
|
|
2019-06-04 12:25:44 +08:00
|
|
|
InMemoryFileSystem->addFile(TestHeaderName, 0,
|
|
|
|
llvm::MemoryBuffer::getMemBuffer(HeaderCode));
|
2018-01-31 20:56:51 +08:00
|
|
|
InMemoryFileSystem->addFile(TestFileName, 0,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::MemoryBuffer::getMemBuffer(MainCode));
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
Invocation.run();
|
|
|
|
Symbols = Factory->Collector->takeSymbols();
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
Refs = Factory->Collector->takeRefs();
|
2019-06-04 12:25:44 +08:00
|
|
|
Relations = Factory->Collector->takeRelations();
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem;
|
2018-02-07 00:10:35 +08:00
|
|
|
std::string TestHeaderName;
|
|
|
|
std::string TestHeaderURI;
|
|
|
|
std::string TestFileName;
|
|
|
|
std::string TestFileURI;
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
SymbolSlab Symbols;
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
RefSlab Refs;
|
2019-06-04 12:25:44 +08:00
|
|
|
RelationSlab Relations;
|
2018-01-10 22:57:58 +08:00
|
|
|
SymbolCollector::Options CollectorOpts;
|
2018-02-16 22:15:55 +08:00
|
|
|
std::unique_ptr<CommentHandler> PragmaHandler;
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
};
|
|
|
|
|
2018-01-10 22:57:58 +08:00
|
|
|
TEST_F(SymbolCollectorTest, CollectSymbols) {
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
const std::string Header = R"(
|
|
|
|
class Foo {
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
Foo() {}
|
|
|
|
Foo(int a) {}
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
void f();
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
friend void f1();
|
|
|
|
friend class Friend;
|
|
|
|
Foo& operator=(const Foo&);
|
|
|
|
~Foo();
|
|
|
|
class Nested {
|
|
|
|
void f();
|
|
|
|
};
|
|
|
|
};
|
|
|
|
class Friend {
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
};
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
void f1();
|
|
|
|
inline void f2() {}
|
2018-01-09 18:44:09 +08:00
|
|
|
static const int KInt = 2;
|
|
|
|
const char* kStr = "123";
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
namespace {
|
|
|
|
void ff() {} // ignore
|
|
|
|
}
|
2018-01-09 18:44:09 +08:00
|
|
|
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
void f1() {}
|
2018-01-09 18:44:09 +08:00
|
|
|
|
|
|
|
namespace foo {
|
|
|
|
// Type alias
|
|
|
|
typedef int int32;
|
|
|
|
using int32_t = int32;
|
|
|
|
|
|
|
|
// Variable
|
|
|
|
int v1;
|
|
|
|
|
|
|
|
// Namespace
|
|
|
|
namespace bar {
|
|
|
|
int v2;
|
|
|
|
}
|
|
|
|
// Namespace alias
|
|
|
|
namespace baz = bar;
|
|
|
|
|
|
|
|
using bar::v2;
|
|
|
|
} // namespace foo
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
)";
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
2018-01-09 18:44:09 +08:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAreArray(
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
{AllOf(QName("Foo"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Foo::Foo"), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::Foo"), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::f"), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::~Foo"), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::operator="), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::Nested"), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::Nested::f"), ForCodeCompletion(false)),
|
|
|
|
|
|
|
|
AllOf(QName("Friend"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("f1"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("f2"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("KInt"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("kStr"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("foo"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("foo::bar"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("foo::int32"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("foo::int32_t"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("foo::v1"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("foo::bar::v2"), ForCodeCompletion(true)),
|
2019-02-26 22:23:47 +08:00
|
|
|
AllOf(QName("foo::v2"), ForCodeCompletion(true)),
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
AllOf(QName("foo::baz"), ForCodeCompletion(true))}));
|
2018-01-29 23:13:29 +08:00
|
|
|
}
|
|
|
|
|
2019-01-14 18:01:17 +08:00
|
|
|
TEST_F(SymbolCollectorTest, FileLocal) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
class Foo {};
|
|
|
|
namespace {
|
|
|
|
class Ignored {};
|
|
|
|
}
|
|
|
|
void bar();
|
|
|
|
)";
|
|
|
|
const std::string Main = R"(
|
|
|
|
class ForwardDecl;
|
|
|
|
void bar() {}
|
|
|
|
static void a();
|
|
|
|
class B {};
|
|
|
|
namespace {
|
|
|
|
void c();
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, Main);
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), VisibleOutsideFile()),
|
|
|
|
AllOf(QName("bar"), VisibleOutsideFile()),
|
|
|
|
AllOf(QName("a"), Not(VisibleOutsideFile())),
|
|
|
|
AllOf(QName("B"), Not(VisibleOutsideFile())),
|
|
|
|
AllOf(QName("c"), Not(VisibleOutsideFile())),
|
|
|
|
// FIXME: ForwardDecl likely *is* visible outside.
|
|
|
|
AllOf(QName("ForwardDecl"), Not(VisibleOutsideFile()))));
|
|
|
|
}
|
|
|
|
|
2018-03-09 21:25:29 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Template) {
|
|
|
|
Annotations Header(R"(
|
[clangd] Store explicit template specializations in index for code navigation purposes
Summary:
This introduces ~4k new symbols, and ~10k refs for LLVM. We need that
information for providing better code navigation support:
- When references for a class template is requested, we should return these specializations as well.
- When children of a specialization is requested, we should be able to query for those symbols(instead of just class template)
Number of symbols: 378574 -> 382784
Number of refs: 5098857 -> 5110689
Reviewers: hokein, gribozavr
Reviewed By: gribozavr
Subscribers: nridge, ilya-biryukov, ioeric, MaskRay, jkorous, arphaman, jdoerfert, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D59083
llvm-svn: 356125
2019-03-14 16:35:17 +08:00
|
|
|
// Primary template and explicit specialization are indexed, instantiation
|
|
|
|
// is not.
|
2019-03-21 06:51:56 +08:00
|
|
|
template <class T, class U> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
|
|
|
|
template <> struct $specdecl[[Tmpl]]<int, bool> {};
|
|
|
|
template <class U> struct $partspecdecl[[Tmpl]]<bool, U> {};
|
|
|
|
extern template struct Tmpl<float, bool>;
|
|
|
|
template struct Tmpl<double, bool>;
|
2018-03-09 21:25:29 +08:00
|
|
|
)");
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"");
|
2019-03-21 06:51:56 +08:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("Tmpl"), DeclRange(Header.range()),
|
|
|
|
ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Tmpl"), DeclRange(Header.range("specdecl")),
|
|
|
|
ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Tmpl"), DeclRange(Header.range("partspecdecl")),
|
|
|
|
ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")),
|
|
|
|
ForCodeCompletion(false))));
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
}
|
|
|
|
|
2019-04-12 18:09:24 +08:00
|
|
|
TEST_F(SymbolCollectorTest, TemplateArgs) {
|
|
|
|
Annotations Header(R"(
|
|
|
|
template <class X> class $barclasstemp[[Bar]] {};
|
|
|
|
template <class T, class U, template<typename> class Z, int Q>
|
|
|
|
struct [[Tmpl]] { T $xdecl[[x]] = 0; };
|
|
|
|
|
|
|
|
// template-template, non-type and type full spec
|
|
|
|
template <> struct $specdecl[[Tmpl]]<int, bool, Bar, 3> {};
|
|
|
|
|
|
|
|
// template-template, non-type and type partial spec
|
|
|
|
template <class U, int T> struct $partspecdecl[[Tmpl]]<bool, U, Bar, T> {};
|
|
|
|
// instantiation
|
|
|
|
extern template struct Tmpl<float, bool, Bar, 8>;
|
|
|
|
// instantiation
|
|
|
|
template struct Tmpl<double, bool, Bar, 2>;
|
|
|
|
|
|
|
|
template <typename ...> class $fooclasstemp[[Foo]] {};
|
|
|
|
// parameter-packs full spec
|
|
|
|
template<> class $parampack[[Foo]]<Bar<int>, int, double> {};
|
|
|
|
// parameter-packs partial spec
|
|
|
|
template<class T> class $parampackpartial[[Foo]]<T, T> {};
|
|
|
|
|
|
|
|
template <int ...> class $bazclasstemp[[Baz]] {};
|
|
|
|
// non-type parameter-packs full spec
|
|
|
|
template<> class $parampacknontype[[Baz]]<3, 5, 8> {};
|
|
|
|
// non-type parameter-packs partial spec
|
|
|
|
template<int T> class $parampacknontypepartial[[Baz]]<T, T> {};
|
|
|
|
|
|
|
|
template <template <class> class ...> class $fozclasstemp[[Foz]] {};
|
|
|
|
// template-template parameter-packs full spec
|
|
|
|
template<> class $parampacktempltempl[[Foz]]<Bar, Bar> {};
|
|
|
|
// template-template parameter-packs partial spec
|
|
|
|
template<template <class> class T>
|
|
|
|
class $parampacktempltemplpartial[[Foz]]<T, T> {};
|
|
|
|
)");
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"");
|
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
AllOf(
|
|
|
|
Contains(AllOf(QName("Tmpl"), TemplateArgs("<int, bool, Bar, 3>"),
|
|
|
|
DeclRange(Header.range("specdecl")),
|
|
|
|
ForCodeCompletion(false))),
|
|
|
|
Contains(AllOf(QName("Tmpl"), TemplateArgs("<bool, U, Bar, T>"),
|
|
|
|
DeclRange(Header.range("partspecdecl")),
|
|
|
|
ForCodeCompletion(false))),
|
|
|
|
Contains(AllOf(QName("Foo"), TemplateArgs("<Bar<int>, int, double>"),
|
|
|
|
DeclRange(Header.range("parampack")),
|
|
|
|
ForCodeCompletion(false))),
|
|
|
|
Contains(AllOf(QName("Foo"), TemplateArgs("<T, T>"),
|
|
|
|
DeclRange(Header.range("parampackpartial")),
|
|
|
|
ForCodeCompletion(false))),
|
|
|
|
Contains(AllOf(QName("Baz"), TemplateArgs("<3, 5, 8>"),
|
|
|
|
DeclRange(Header.range("parampacknontype")),
|
|
|
|
ForCodeCompletion(false))),
|
|
|
|
Contains(AllOf(QName("Baz"), TemplateArgs("<T, T>"),
|
|
|
|
DeclRange(Header.range("parampacknontypepartial")),
|
|
|
|
ForCodeCompletion(false))),
|
|
|
|
Contains(AllOf(QName("Foz"), TemplateArgs("<Bar, Bar>"),
|
|
|
|
DeclRange(Header.range("parampacktempltempl")),
|
|
|
|
ForCodeCompletion(false))),
|
|
|
|
Contains(AllOf(QName("Foz"), TemplateArgs("<T, T>"),
|
|
|
|
DeclRange(Header.range("parampacktempltemplpartial")),
|
|
|
|
ForCodeCompletion(false)))));
|
|
|
|
}
|
|
|
|
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
TEST_F(SymbolCollectorTest, ObjCSymbols) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
@interface Person
|
|
|
|
- (void)someMethodName:(void*)name1 lastName:(void*)lName;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Person
|
|
|
|
- (void)someMethodName:(void*)name1 lastName:(void*)lName{
|
|
|
|
int foo;
|
|
|
|
^(int param){ int bar; };
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@interface Person (MyCategory)
|
|
|
|
- (void)someMethodName2:(void*)name2;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Person (MyCategory)
|
|
|
|
- (void)someMethodName2:(void*)name2 {
|
|
|
|
int foo2;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
@protocol MyProtocol
|
|
|
|
- (void)someMethodName3:(void*)name3;
|
|
|
|
@end
|
|
|
|
)";
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
TestFileName = testPath("test.m");
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
runSymbolCollector(Header, /*Main=*/"", {"-fblocks", "-xobjective-c++"});
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("Person"), QName("Person::someMethodName:lastName:"),
|
|
|
|
QName("MyCategory"), QName("Person::someMethodName2:"),
|
|
|
|
QName("MyProtocol"), QName("MyProtocol::someMethodName3:")));
|
2018-03-09 21:25:29 +08:00
|
|
|
}
|
|
|
|
|
2019-01-23 18:35:12 +08:00
|
|
|
TEST_F(SymbolCollectorTest, ObjCPropertyImpl) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
@interface Container
|
|
|
|
@property(nonatomic) int magic;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation Container
|
|
|
|
@end
|
|
|
|
)";
|
|
|
|
TestFileName = testPath("test.m");
|
|
|
|
runSymbolCollector(Header, /*Main=*/"", {"-xobjective-c++"});
|
2019-01-23 19:32:07 +08:00
|
|
|
EXPECT_THAT(Symbols, Contains(QName("Container")));
|
|
|
|
EXPECT_THAT(Symbols, Contains(QName("Container::magic")));
|
|
|
|
// FIXME: Results also contain Container::_magic on some platforms.
|
|
|
|
// Figure out why it's platform-dependent.
|
2019-01-23 18:35:12 +08:00
|
|
|
}
|
|
|
|
|
2018-02-09 22:42:01 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Locations) {
|
|
|
|
Annotations Header(R"cpp(
|
|
|
|
// Declared in header, defined in main.
|
2018-02-13 17:53:50 +08:00
|
|
|
extern int $xdecl[[X]];
|
|
|
|
class $clsdecl[[Cls]];
|
|
|
|
void $printdecl[[print]]();
|
2018-02-09 22:42:01 +08:00
|
|
|
|
|
|
|
// Declared in header, defined nowhere.
|
2018-02-13 17:53:50 +08:00
|
|
|
extern int $zdecl[[Z]];
|
2018-04-13 16:30:39 +08:00
|
|
|
|
|
|
|
void $foodecl[[fo\
|
|
|
|
o]]();
|
2018-02-09 22:42:01 +08:00
|
|
|
)cpp");
|
|
|
|
Annotations Main(R"cpp(
|
2018-02-13 17:53:50 +08:00
|
|
|
int $xdef[[X]] = 42;
|
|
|
|
class $clsdef[[Cls]] {};
|
|
|
|
void $printdef[[print]]() {}
|
2018-02-09 22:42:01 +08:00
|
|
|
|
|
|
|
// Declared/defined in main only.
|
2019-01-14 18:01:17 +08:00
|
|
|
int $ydecl[[Y]];
|
2018-02-09 22:42:01 +08:00
|
|
|
)cpp");
|
|
|
|
runSymbolCollector(Header.code(), Main.code());
|
2019-01-03 21:28:05 +08:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("X"), DeclRange(Header.range("xdecl")),
|
|
|
|
DefRange(Main.range("xdef"))),
|
|
|
|
AllOf(QName("Cls"), DeclRange(Header.range("clsdecl")),
|
|
|
|
DefRange(Main.range("clsdef"))),
|
|
|
|
AllOf(QName("print"), DeclRange(Header.range("printdecl")),
|
|
|
|
DefRange(Main.range("printdef"))),
|
|
|
|
AllOf(QName("Z"), DeclRange(Header.range("zdecl"))),
|
2019-01-14 18:01:17 +08:00
|
|
|
AllOf(QName("foo"), DeclRange(Header.range("foodecl"))),
|
|
|
|
AllOf(QName("Y"), DeclRange(Main.range("ydecl")))));
|
2018-02-09 22:42:01 +08:00
|
|
|
}
|
|
|
|
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Refs) {
|
2018-08-31 20:54:13 +08:00
|
|
|
Annotations Header(R"(
|
|
|
|
class $foo[[Foo]] {
|
|
|
|
public:
|
|
|
|
$foo[[Foo]]() {}
|
|
|
|
$foo[[Foo]](int);
|
|
|
|
};
|
|
|
|
class $bar[[Bar]];
|
|
|
|
void $func[[func]]();
|
2018-11-07 22:59:24 +08:00
|
|
|
|
|
|
|
namespace $ns[[NS]] {} // namespace ref is ignored
|
2018-08-31 20:54:13 +08:00
|
|
|
)");
|
|
|
|
Annotations Main(R"(
|
|
|
|
class $bar[[Bar]] {};
|
|
|
|
|
|
|
|
void $func[[func]]();
|
|
|
|
|
|
|
|
void fff() {
|
|
|
|
$foo[[Foo]] foo;
|
|
|
|
$bar[[Bar]] bar;
|
|
|
|
$func[[func]]();
|
|
|
|
int abc = 0;
|
|
|
|
$foo[[Foo]] foo2 = abc;
|
|
|
|
}
|
|
|
|
)");
|
|
|
|
Annotations SymbolsOnlyInMainCode(R"(
|
|
|
|
int a;
|
|
|
|
void b() {}
|
|
|
|
static const int c = 0;
|
|
|
|
class d {};
|
|
|
|
)");
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
CollectorOpts.RefFilter = RefKind::All;
|
2018-08-31 20:54:13 +08:00
|
|
|
runSymbolCollector(Header.code(),
|
|
|
|
(Main.code() + SymbolsOnlyInMainCode.code()).str());
|
|
|
|
auto HeaderSymbols = TestTU::withHeaderCode(Header.code()).headerSymbols();
|
|
|
|
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Foo").ID,
|
|
|
|
HaveRanges(Main.ranges("foo")))));
|
|
|
|
EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Bar").ID,
|
|
|
|
HaveRanges(Main.ranges("bar")))));
|
|
|
|
EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "func").ID,
|
|
|
|
HaveRanges(Main.ranges("func")))));
|
2018-11-07 22:59:24 +08:00
|
|
|
EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(Symbols, "NS").ID, _))));
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
// Symbols *only* in the main file (a, b, c) had no refs collected.
|
2018-08-31 20:54:13 +08:00
|
|
|
auto MainSymbols =
|
|
|
|
TestTU::withHeaderCode(SymbolsOnlyInMainCode.code()).headerSymbols();
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(MainSymbols, "a").ID, _))));
|
|
|
|
EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(MainSymbols, "b").ID, _))));
|
|
|
|
EXPECT_THAT(Refs, Not(Contains(Pair(findSymbol(MainSymbols, "c").ID, _))));
|
2018-08-31 20:54:13 +08:00
|
|
|
}
|
|
|
|
|
2018-10-17 16:38:36 +08:00
|
|
|
TEST_F(SymbolCollectorTest, RefsInHeaders) {
|
|
|
|
CollectorOpts.RefFilter = RefKind::All;
|
|
|
|
CollectorOpts.RefsInHeaders = true;
|
|
|
|
Annotations Header(R"(
|
|
|
|
class [[Foo]] {};
|
|
|
|
)");
|
|
|
|
runSymbolCollector(Header.code(), "");
|
|
|
|
EXPECT_THAT(Refs, Contains(Pair(findSymbol(Symbols, "Foo").ID,
|
|
|
|
HaveRanges(Header.ranges()))));
|
|
|
|
}
|
|
|
|
|
2019-06-04 12:25:44 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Relations) {
|
|
|
|
std::string Header = R"(
|
|
|
|
class Base {};
|
|
|
|
class Derived : public Base {};
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
|
|
|
const Symbol &Base = findSymbol(Symbols, "Base");
|
|
|
|
const Symbol &Derived = findSymbol(Symbols, "Derived");
|
|
|
|
EXPECT_THAT(Relations,
|
|
|
|
Contains(Relation{Base.ID, index::SymbolRole::RelationBaseOf,
|
|
|
|
Derived.ID}));
|
|
|
|
}
|
|
|
|
|
2018-03-12 22:49:09 +08:00
|
|
|
TEST_F(SymbolCollectorTest, References) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
class W;
|
|
|
|
class X {};
|
|
|
|
class Y;
|
|
|
|
class Z {}; // not used anywhere
|
|
|
|
Y* y = nullptr; // used in header doesn't count
|
2018-04-09 22:28:52 +08:00
|
|
|
#define GLOBAL_Z(name) Z name;
|
2018-03-12 22:49:09 +08:00
|
|
|
)";
|
|
|
|
const std::string Main = R"(
|
|
|
|
W* w = nullptr;
|
|
|
|
W* w2 = nullptr; // only one usage counts
|
|
|
|
X x();
|
|
|
|
class V;
|
|
|
|
class Y{}; // definition doesn't count as a reference
|
2019-01-14 18:01:17 +08:00
|
|
|
V* v = nullptr;
|
2018-04-09 22:28:52 +08:00
|
|
|
GLOBAL_Z(z); // Not a reference to Z, we don't spell the type.
|
2018-03-12 22:49:09 +08:00
|
|
|
)";
|
|
|
|
CollectorOpts.CountReferences = true;
|
|
|
|
runSymbolCollector(Header, Main);
|
2019-05-06 18:08:47 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAreArray(
|
|
|
|
{AllOf(QName("W"), RefCount(1)), AllOf(QName("X"), RefCount(1)),
|
|
|
|
AllOf(QName("Y"), RefCount(0)), AllOf(QName("Z"), RefCount(0)),
|
|
|
|
AllOf(QName("y"), RefCount(0)), AllOf(QName("z"), RefCount(0)),
|
|
|
|
AllOf(QName("x"), RefCount(0)), AllOf(QName("w"), RefCount(0)),
|
|
|
|
AllOf(QName("w2"), RefCount(0)), AllOf(QName("V"), RefCount(1)),
|
|
|
|
AllOf(QName("v"), RefCount(0))}));
|
2018-03-12 22:49:09 +08:00
|
|
|
}
|
|
|
|
|
2018-01-29 23:13:29 +08:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolRelativeNoFallback) {
|
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
|
2018-01-29 23:13:29 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, SymbolRelativeWithFallback) {
|
2018-02-07 00:10:35 +08:00
|
|
|
TestHeaderName = "x.h";
|
|
|
|
TestFileName = "x.cpp";
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
TestHeaderURI = URI::create(testPath(TestHeaderName)).toString();
|
2018-02-16 17:41:43 +08:00
|
|
|
CollectorOpts.FallbackDir = testRoot();
|
2018-01-29 23:13:29 +08:00
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
2019-01-03 21:28:05 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
|
2018-02-07 00:10:35 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
TEST_F(SymbolCollectorTest, UnittestURIScheme) {
|
2018-02-07 00:10:35 +08:00
|
|
|
// Use test URI scheme from URITests.cpp
|
2018-06-15 16:55:00 +08:00
|
|
|
TestHeaderName = testPath("x.h");
|
|
|
|
TestFileName = testPath("x.cpp");
|
2018-02-07 00:10:35 +08:00
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
2018-06-15 16:55:00 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI("unittest:///x.h"))));
|
2018-02-07 00:10:35 +08:00
|
|
|
}
|
|
|
|
|
2018-01-19 17:35:55 +08:00
|
|
|
TEST_F(SymbolCollectorTest, IncludeEnums) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
enum {
|
|
|
|
Red
|
|
|
|
};
|
|
|
|
enum Color {
|
|
|
|
Green
|
|
|
|
};
|
|
|
|
enum class Color2 {
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
Yellow
|
2018-01-19 17:35:55 +08:00
|
|
|
};
|
|
|
|
namespace ns {
|
|
|
|
enum {
|
|
|
|
Black
|
|
|
|
};
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("Red"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Color"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Green"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Color2"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Color2::Yellow"), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("ns"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("ns::Black"), ForCodeCompletion(true))));
|
2018-01-19 17:35:55 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
TEST_F(SymbolCollectorTest, NamelessSymbols) {
|
2018-01-19 17:35:55 +08:00
|
|
|
const std::string Header = R"(
|
|
|
|
struct {
|
|
|
|
int a;
|
|
|
|
} Foo;
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo"),
|
|
|
|
QName("(anonymous struct)::a")));
|
2018-01-19 17:35:55 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolFormedFromRegisteredSchemeFromMacro) {
|
2018-01-31 20:56:51 +08:00
|
|
|
|
|
|
|
Annotations Header(R"(
|
|
|
|
#define FF(name) \
|
|
|
|
class name##_Test {};
|
|
|
|
|
2018-02-13 17:53:50 +08:00
|
|
|
$expansion[[FF]](abc);
|
2018-01-31 20:56:51 +08:00
|
|
|
|
|
|
|
#define FF2() \
|
2018-02-13 17:53:50 +08:00
|
|
|
class $spelling[[Test]] {};
|
2018-01-31 20:56:51 +08:00
|
|
|
|
|
|
|
FF2();
|
|
|
|
)");
|
|
|
|
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"");
|
2019-01-03 21:28:05 +08:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("abc_Test"), DeclRange(Header.range("expansion")),
|
|
|
|
DeclURI(TestHeaderURI)),
|
|
|
|
AllOf(QName("Test"), DeclRange(Header.range("spelling")),
|
|
|
|
DeclURI(TestHeaderURI))));
|
2018-01-31 20:56:51 +08:00
|
|
|
}
|
|
|
|
|
2018-12-05 19:57:15 +08:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolFormedByCLI) {
|
|
|
|
Annotations Header(R"(
|
|
|
|
#ifdef NAME
|
|
|
|
class $expansion[[NAME]] {};
|
|
|
|
#endif
|
|
|
|
)");
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"", /*ExtraArgs=*/{"-DNAME=name"});
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
|
|
|
|
QName("name"), DeclRange(Header.range("expansion")),
|
|
|
|
DeclURI(TestHeaderURI))));
|
|
|
|
}
|
|
|
|
|
2019-01-14 18:01:17 +08:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolsInMainFile) {
|
|
|
|
const std::string Main = R"(
|
2018-01-10 22:57:58 +08:00
|
|
|
class Foo {};
|
|
|
|
void f1();
|
|
|
|
inline void f2() {}
|
2019-01-14 18:01:17 +08:00
|
|
|
|
2018-01-10 22:57:58 +08:00
|
|
|
namespace {
|
2019-01-14 18:01:17 +08:00
|
|
|
void ff() {}
|
2018-01-10 22:57:58 +08:00
|
|
|
}
|
2019-01-14 18:01:17 +08:00
|
|
|
namespace foo {
|
|
|
|
namespace {
|
|
|
|
class Bar {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void main_f() {}
|
2018-01-10 22:57:58 +08:00
|
|
|
void f1() {}
|
|
|
|
)";
|
2019-01-14 18:01:17 +08:00
|
|
|
runSymbolCollector(/*Header=*/"", Main);
|
2019-06-04 12:25:44 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
QName("Foo"), QName("f1"), QName("f2"), QName("ff"),
|
|
|
|
QName("foo"), QName("foo::Bar"), QName("main_f")));
|
2018-01-10 22:57:58 +08:00
|
|
|
}
|
|
|
|
|
2019-02-26 00:00:00 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Documentation) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
// Doc Foo
|
|
|
|
class Foo {
|
|
|
|
// Doc f
|
|
|
|
int f();
|
|
|
|
};
|
|
|
|
)";
|
|
|
|
CollectorOpts.StoreAllDocumentation = false;
|
|
|
|
runSymbolCollector(Header, /* Main */ "");
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), Doc("Doc Foo"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Foo::f"), Doc(""), ReturnType(""),
|
|
|
|
ForCodeCompletion(false))));
|
|
|
|
|
|
|
|
CollectorOpts.StoreAllDocumentation = true;
|
|
|
|
runSymbolCollector(Header, /* Main */ "");
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), Doc("Doc Foo"), ForCodeCompletion(true)),
|
|
|
|
AllOf(QName("Foo::f"), Doc("Doc f"), ReturnType(""),
|
|
|
|
ForCodeCompletion(false))));
|
|
|
|
}
|
|
|
|
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
TEST_F(SymbolCollectorTest, ClassMembers) {
|
2018-01-10 22:57:58 +08:00
|
|
|
const std::string Header = R"(
|
|
|
|
class Foo {
|
|
|
|
void f() {}
|
|
|
|
void g();
|
|
|
|
static void sf() {}
|
|
|
|
static void ssf();
|
|
|
|
static int x;
|
|
|
|
};
|
|
|
|
)";
|
2018-01-10 01:32:00 +08:00
|
|
|
const std::string Main = R"(
|
2018-01-10 22:57:58 +08:00
|
|
|
void Foo::g() {}
|
|
|
|
void Foo::ssf() {}
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, Main);
|
2019-01-10 17:22:40 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("Foo"),
|
|
|
|
AllOf(QName("Foo::f"), ReturnType(""), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::g"), ReturnType(""), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::sf"), ReturnType(""), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::ssf"), ReturnType(""), ForCodeCompletion(false)),
|
|
|
|
AllOf(QName("Foo::x"), ReturnType(""), ForCodeCompletion(false))));
|
2018-01-10 22:57:58 +08:00
|
|
|
}
|
|
|
|
|
2018-02-02 18:31:42 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Scopes) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
namespace na {
|
|
|
|
class Foo {};
|
|
|
|
namespace nb {
|
|
|
|
class Bar {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(QName("na"), QName("na::nb"),
|
|
|
|
QName("na::Foo"), QName("na::nb::Bar")));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, ExternC) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
extern "C" { class Foo {}; }
|
|
|
|
namespace na {
|
|
|
|
extern "C" { class Bar {}; }
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
2018-02-03 01:01:36 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(QName("na"), QName("Foo"),
|
|
|
|
QName("na::Bar")));
|
2018-02-02 18:31:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, SkipInlineNamespace) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
namespace na {
|
|
|
|
inline namespace nb {
|
|
|
|
class Foo {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
namespace na {
|
|
|
|
// This is still inlined.
|
|
|
|
namespace nb {
|
|
|
|
class Bar {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(QName("na"), QName("na::nb"),
|
|
|
|
QName("na::Foo"), QName("na::Bar")));
|
|
|
|
}
|
|
|
|
|
2018-01-10 22:57:58 +08:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolWithDocumentation) {
|
|
|
|
const std::string Header = R"(
|
2018-01-10 01:32:00 +08:00
|
|
|
namespace nx {
|
|
|
|
/// Foo comment.
|
|
|
|
int ff(int x, double y) { return 0; }
|
|
|
|
}
|
|
|
|
)";
|
2018-01-10 22:57:58 +08:00
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
2018-05-16 20:32:44 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("nx"), AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"),
|
2018-06-23 00:11:35 +08:00
|
|
|
ReturnType("int"), Doc("Foo comment."))));
|
2018-01-10 01:32:00 +08:00
|
|
|
}
|
|
|
|
|
2018-06-23 00:11:35 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Snippet) {
|
2018-01-10 22:57:58 +08:00
|
|
|
const std::string Header = R"(
|
2018-01-10 01:32:00 +08:00
|
|
|
namespace nx {
|
|
|
|
void f() {}
|
|
|
|
int ff(int x, double y) { return 0; }
|
|
|
|
}
|
|
|
|
)";
|
2018-01-10 22:57:58 +08:00
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
2018-06-23 00:11:35 +08:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("nx"),
|
|
|
|
AllOf(QName("nx::f"), Labeled("f()"), Snippet("f()")),
|
|
|
|
AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"),
|
|
|
|
Snippet("ff(${1:int x}, ${2:double y})"))));
|
2018-01-10 01:32:00 +08:00
|
|
|
}
|
|
|
|
|
2018-02-16 22:15:55 +08:00
|
|
|
TEST_F(SymbolCollectorTest, IncludeHeaderSameAsFileURI) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
runSymbolCollector("#pragma once\nclass Foo {};", /*Main=*/"");
|
[clangd] Support multiple #include headers in one symbol.
Summary:
Currently, a symbol can have only one #include header attached, which
might not work well if the symbol can be imported via different #includes depending
on where it's used. This patch stores multiple #include headers (with # references)
for each symbol, so that CodeCompletion can decide which include to insert.
In this patch, code completion simply picks the most popular include as the default inserted header. We also return all possible includes and their edits in the `CodeCompletion` results.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: mgrang, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51291
llvm-svn: 341304
2018-09-03 18:18:21 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
|
|
|
|
EXPECT_THAT(Symbols.begin()->IncludeHeaders,
|
|
|
|
UnorderedElementsAre(IncludeHeaderWithRef(TestHeaderURI, 1u)));
|
2018-02-16 22:15:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, CanonicalSTLHeader) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
2019-06-21 21:32:18 +08:00
|
|
|
auto Language = LangOptions();
|
|
|
|
Language.CPlusPlus = true;
|
|
|
|
addSystemHeadersMapping(&Includes, Language);
|
2018-02-16 22:15:55 +08:00
|
|
|
CollectorOpts.Includes = &Includes;
|
2019-04-29 22:36:26 +08:00
|
|
|
runSymbolCollector("namespace std { class string {}; }", /*Main=*/"");
|
2018-03-02 02:06:40 +08:00
|
|
|
EXPECT_THAT(Symbols,
|
2019-04-29 22:36:26 +08:00
|
|
|
Contains(AllOf(QName("std::string"), DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader("<string>"))));
|
2018-03-02 02:06:40 +08:00
|
|
|
}
|
|
|
|
|
2018-02-16 22:15:55 +08:00
|
|
|
TEST_F(SymbolCollectorTest, IWYUPragma) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
PragmaHandler = collectIWYUHeaderMaps(&Includes);
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
const std::string Header = R"(
|
|
|
|
// IWYU pragma: private, include the/good/header.h
|
|
|
|
class Foo {};
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader("\"the/good/header.h\""))));
|
|
|
|
}
|
|
|
|
|
2018-05-22 16:33:30 +08:00
|
|
|
TEST_F(SymbolCollectorTest, IWYUPragmaWithDoubleQuotes) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
PragmaHandler = collectIWYUHeaderMaps(&Includes);
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
const std::string Header = R"(
|
|
|
|
// IWYU pragma: private, include "the/good/header.h"
|
|
|
|
class Foo {};
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader("\"the/good/header.h\""))));
|
|
|
|
}
|
|
|
|
|
2018-05-24 22:40:24 +08:00
|
|
|
TEST_F(SymbolCollectorTest, SkipIncFileWhenCanonicalizeHeaders) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
Includes.addMapping(TestHeaderName, "<canonical>");
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
auto IncFile = testPath("test.inc");
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
auto IncURI = URI::create(IncFile).toString();
|
2018-05-24 22:40:24 +08:00
|
|
|
InMemoryFileSystem->addFile(IncFile, 0,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::MemoryBuffer::getMemBuffer("class X {};"));
|
2018-05-24 22:40:24 +08:00
|
|
|
runSymbolCollector("#include \"test.inc\"\nclass Y {};", /*Main=*/"",
|
|
|
|
/*ExtraArgs=*/{"-I", testRoot()});
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
|
|
|
|
IncludeHeader("<canonical>")),
|
|
|
|
AllOf(QName("Y"), DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader("<canonical>"))));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, MainFileIsHeaderWhenSkipIncFile) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
// To make this case as hard as possible, we won't tell clang main is a
|
|
|
|
// header. No extension, no -x c++-header.
|
|
|
|
TestFileName = testPath("no_ext_main");
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
TestFileURI = URI::create(TestFileName).toString();
|
2018-05-24 22:40:24 +08:00
|
|
|
auto IncFile = testPath("test.inc");
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
auto IncURI = URI::create(IncFile).toString();
|
2018-05-24 22:40:24 +08:00
|
|
|
InMemoryFileSystem->addFile(IncFile, 0,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::MemoryBuffer::getMemBuffer("class X {};"));
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
runSymbolCollector("", R"cpp(
|
|
|
|
// Can't use #pragma once in a main file clang doesn't think is a header.
|
|
|
|
#ifndef MAIN_H_
|
|
|
|
#define MAIN_H_
|
|
|
|
#include "test.inc"
|
|
|
|
#endif
|
|
|
|
)cpp",
|
2018-05-24 22:40:24 +08:00
|
|
|
/*ExtraArgs=*/{"-I", testRoot()});
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
|
|
|
|
IncludeHeader(TestFileURI))));
|
|
|
|
}
|
|
|
|
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
TEST_F(SymbolCollectorTest, IncFileInNonHeader) {
|
2018-05-24 22:40:24 +08:00
|
|
|
CollectorOpts.CollectIncludePath = true;
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
TestFileName = testPath("main.cc");
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
TestFileURI = URI::create(TestFileName).toString();
|
2018-05-24 22:40:24 +08:00
|
|
|
auto IncFile = testPath("test.inc");
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
auto IncURI = URI::create(IncFile).toString();
|
2018-05-24 22:40:24 +08:00
|
|
|
InMemoryFileSystem->addFile(IncFile, 0,
|
2019-01-07 23:45:19 +08:00
|
|
|
llvm::MemoryBuffer::getMemBuffer("class X {};"));
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
runSymbolCollector("", R"cpp(
|
|
|
|
#include "test.inc"
|
|
|
|
)cpp",
|
2018-05-24 22:40:24 +08:00
|
|
|
/*ExtraArgs=*/{"-I", testRoot()});
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
Not(IncludeHeader()))));
|
2018-05-24 22:40:24 +08:00
|
|
|
}
|
|
|
|
|
2019-05-03 21:17:29 +08:00
|
|
|
// Features that depend on header-guards are fragile. Header guards are only
|
|
|
|
// recognized when the file ends, so we have to defer checking for them.
|
|
|
|
TEST_F(SymbolCollectorTest, HeaderGuardDetected) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CollectorOpts.CollectMacro = true;
|
|
|
|
runSymbolCollector(R"cpp(
|
|
|
|
#ifndef HEADER_GUARD_
|
|
|
|
#define HEADER_GUARD_
|
|
|
|
|
|
|
|
// Symbols are seen before the header guard is complete.
|
|
|
|
#define MACRO
|
|
|
|
int decl();
|
|
|
|
|
|
|
|
#endif // Header guard is recognized here.
|
|
|
|
)cpp",
|
|
|
|
"");
|
|
|
|
EXPECT_THAT(Symbols, Not(Contains(QName("HEADER_GUARD_"))));
|
|
|
|
EXPECT_THAT(Symbols, Each(IncludeHeader()));
|
|
|
|
}
|
|
|
|
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
TEST_F(SymbolCollectorTest, NonModularHeader) {
|
|
|
|
auto TU = TestTU::withHeaderCode("int x();");
|
|
|
|
EXPECT_THAT(TU.headerSymbols(), ElementsAre(IncludeHeader()));
|
|
|
|
|
2019-04-18 02:33:07 +08:00
|
|
|
// Files missing include guards aren't eligible for insertion.
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
TU.ImplicitHeaderGuard = false;
|
|
|
|
EXPECT_THAT(TU.headerSymbols(), ElementsAre(Not(IncludeHeader())));
|
2019-04-18 02:33:07 +08:00
|
|
|
|
|
|
|
// We recognize some patterns of trying to prevent insertion.
|
|
|
|
TU = TestTU::withHeaderCode(R"cpp(
|
|
|
|
#ifndef SECRET
|
|
|
|
#error "This file isn't safe to include directly"
|
|
|
|
#endif
|
|
|
|
int x();
|
|
|
|
)cpp");
|
|
|
|
TU.ExtraArgs.push_back("-DSECRET"); // *we're* able to include it.
|
|
|
|
EXPECT_THAT(TU.headerSymbols(), ElementsAre(Not(IncludeHeader())));
|
2018-05-24 22:40:24 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
TEST_F(SymbolCollectorTest, AvoidUsingFwdDeclsAsCanonicalDecls) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
Annotations Header(R"(
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
#pragma once
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
// Forward declarations of TagDecls.
|
|
|
|
class C;
|
|
|
|
struct S;
|
|
|
|
union U;
|
|
|
|
|
|
|
|
// Canonical declarations.
|
|
|
|
class $cdecl[[C]] {};
|
|
|
|
struct $sdecl[[S]] {};
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
union $udecl[[U]] {int $xdecl[[x]]; bool $ydecl[[y]];};
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
)");
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"");
|
[clangd] Add "member" symbols to the index
Summary:
This adds more symbols to the index:
- member variables and functions
- enum constants in scoped enums
The code completion behavior should remain intact but workspace symbols should
now provide much more useful symbols.
Other symbols should be considered such as the ones in "main files" (files not
being included) but this can be done separately as this introduces its fair
share of problems.
Signed-off-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Reviewers: ioeric, sammccall
Reviewed By: ioeric, sammccall
Subscribers: hokein, sammccall, jkorous, klimek, ilya-biryukov, jkorous-apple, ioeric, MaskRay, cfe-commits
Differential Revision: https://reviews.llvm.org/D44954
llvm-svn: 334017
2018-06-05 22:01:40 +08:00
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("C"), DeclURI(TestHeaderURI),
|
|
|
|
DeclRange(Header.range("cdecl")), IncludeHeader(TestHeaderURI),
|
|
|
|
DefURI(TestHeaderURI), DefRange(Header.range("cdecl"))),
|
|
|
|
AllOf(QName("S"), DeclURI(TestHeaderURI),
|
|
|
|
DeclRange(Header.range("sdecl")), IncludeHeader(TestHeaderURI),
|
|
|
|
DefURI(TestHeaderURI), DefRange(Header.range("sdecl"))),
|
|
|
|
AllOf(QName("U"), DeclURI(TestHeaderURI),
|
|
|
|
DeclRange(Header.range("udecl")), IncludeHeader(TestHeaderURI),
|
|
|
|
DefURI(TestHeaderURI), DefRange(Header.range("udecl"))),
|
|
|
|
AllOf(QName("U::x"), DeclURI(TestHeaderURI),
|
|
|
|
DeclRange(Header.range("xdecl")), DefURI(TestHeaderURI),
|
|
|
|
DefRange(Header.range("xdecl"))),
|
|
|
|
AllOf(QName("U::y"), DeclURI(TestHeaderURI),
|
|
|
|
DeclRange(Header.range("ydecl")), DefURI(TestHeaderURI),
|
|
|
|
DefRange(Header.range("ydecl")))));
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, ClassForwardDeclarationIsCanonical) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
runSymbolCollector(/*Header=*/"#pragma once\nclass X;",
|
|
|
|
/*Main=*/"class X {};");
|
[clangd] Prefer the definition of a TagDecl (e.g. class) as CanonicalDeclaration.
Summary:
Currently, we pick the first declaration of a symbol in a TU, which is considered
canonical in the clangIndex, as the canonical declaration in clangd. This causes
forward declarations that might appear in a random header to be used as a
canonical declaration, which is not desirable for features like go-to-declaration
or include insertion.
For example, for class X, we would consider the forward declaration in fwd.h to
be the canonical declaration, while the preferred canonical declaration should
be the actual definition in x.h.
```
// fwd.h
class X; // forward decl
// x.h
class X {};
```
This patch fixes the issue by making symbol collector favor the actual definition of
a TagDecl (i.e. class/struct/enum/union) found in a header file over the first seen
declarations in a TU. Other symbol types like functions are not handled because
using the first seen declarations as canonical declarations is usually a good
heuristic for them.
Reviewers: sammccall
Subscribers: klimek, ilya-biryukov, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43823
llvm-svn: 326313
2018-02-28 17:33:15 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
|
|
|
|
QName("X"), DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader(TestHeaderURI), DefURI(TestFileURI))));
|
|
|
|
}
|
|
|
|
|
2018-04-30 19:40:02 +08:00
|
|
|
TEST_F(SymbolCollectorTest, UTF16Character) {
|
|
|
|
// ö is 2-bytes.
|
|
|
|
Annotations Header(/*Header=*/"class [[pörk]] {};");
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("pörk"), DeclRange(Header.range()))));
|
|
|
|
}
|
|
|
|
|
2018-06-04 19:31:55 +08:00
|
|
|
TEST_F(SymbolCollectorTest, DoNotIndexSymbolsInFriendDecl) {
|
|
|
|
Annotations Header(R"(
|
|
|
|
namespace nx {
|
|
|
|
class $z[[Z]] {};
|
|
|
|
class X {
|
|
|
|
friend class Y;
|
|
|
|
friend class Z;
|
|
|
|
friend void foo();
|
|
|
|
friend void $bar[[bar]]() {}
|
|
|
|
};
|
|
|
|
class $y[[Y]] {};
|
|
|
|
void $foo[[foo]]();
|
|
|
|
}
|
|
|
|
)");
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"");
|
|
|
|
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("nx"), QName("nx::X"),
|
|
|
|
AllOf(QName("nx::Y"), DeclRange(Header.range("y"))),
|
|
|
|
AllOf(QName("nx::Z"), DeclRange(Header.range("z"))),
|
|
|
|
AllOf(QName("nx::foo"), DeclRange(Header.range("foo"))),
|
|
|
|
AllOf(QName("nx::bar"), DeclRange(Header.range("bar")))));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, ReferencesInFriendDecl) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
class X;
|
|
|
|
class Y;
|
|
|
|
)";
|
|
|
|
const std::string Main = R"(
|
|
|
|
class C {
|
|
|
|
friend ::X;
|
|
|
|
friend class Y;
|
|
|
|
};
|
|
|
|
)";
|
|
|
|
CollectorOpts.CountReferences = true;
|
|
|
|
runSymbolCollector(Header, Main);
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), RefCount(1)),
|
2019-01-14 18:01:17 +08:00
|
|
|
AllOf(QName("Y"), RefCount(1)),
|
|
|
|
AllOf(QName("C"), RefCount(0))));
|
2018-06-04 19:31:55 +08:00
|
|
|
}
|
|
|
|
|
2018-07-05 14:20:41 +08:00
|
|
|
TEST_F(SymbolCollectorTest, Origin) {
|
|
|
|
CollectorOpts.Origin = SymbolOrigin::Static;
|
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
Field(&Symbol::Origin, SymbolOrigin::Static)));
|
|
|
|
}
|
|
|
|
|
2018-07-09 23:31:07 +08:00
|
|
|
TEST_F(SymbolCollectorTest, CollectMacros) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
Annotations Header(R"(
|
[clangd] Include insertion: require header guards, drop other heuristics, treat .def like .inc.
Summary:
We do have some reports of include insertion behaving badly in some
codebases. Requiring header guards both makes sense in principle, and is
likely to disable this "nice-to-have" feature in codebases where headers don't
follow the expected pattern.
With this we can drop some other heuristics, such as looking at file
extensions to detect known non-headers - implementation files have no guards.
One wrinkle here is #import - objc headers may not have guards because
they're intended to be used via #import. If the header is the main file
or is #included, we won't collect locations - merge should take care of
this if we see the file #imported somewhere. Seems likely to be OK.
Headers which have a canonicalization (stdlib, IWYU) are exempt from this check.
*.inc files continue to be handled by looking up to the including file.
This patch also adds *.def here - tablegen wants this pattern too.
In terms of code structure, the division between SymbolCollector and
CanonicalIncludes has shifted: SymbolCollector is responsible for more.
This is because SymbolCollector has all the SourceManager/HeaderSearch access
needed for checking for guards, and we interleave these checks with the *.def
checks in a loop (potentially).
We could hand all the info into CanonicalIncludes and put the logic there
if that's preferable.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D60316
llvm-svn: 358571
2019-04-17 18:36:02 +08:00
|
|
|
#pragma once
|
2018-07-09 23:31:07 +08:00
|
|
|
#define X 1
|
|
|
|
#define $mac[[MAC]](x) int x
|
|
|
|
#define $used[[USED]](y) float y;
|
|
|
|
|
|
|
|
MAC(p);
|
|
|
|
)");
|
2019-01-28 22:11:49 +08:00
|
|
|
|
|
|
|
Annotations Main(R"(
|
|
|
|
#define $main[[MAIN]] 1
|
|
|
|
USED(t);
|
|
|
|
)");
|
2018-07-09 23:31:07 +08:00
|
|
|
CollectorOpts.CountReferences = true;
|
|
|
|
CollectorOpts.CollectMacro = true;
|
2019-01-28 22:11:49 +08:00
|
|
|
runSymbolCollector(Header.code(), Main.code());
|
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("p"), QName("t"),
|
|
|
|
AllOf(QName("X"), DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader(TestHeaderURI)),
|
|
|
|
AllOf(Labeled("MAC(x)"), RefCount(0),
|
|
|
|
|
|
|
|
DeclRange(Header.range("mac")), VisibleOutsideFile()),
|
|
|
|
AllOf(Labeled("USED(y)"), RefCount(1),
|
|
|
|
DeclRange(Header.range("used")), VisibleOutsideFile()),
|
|
|
|
AllOf(Labeled("MAIN"), RefCount(0), DeclRange(Main.range("main")),
|
|
|
|
Not(VisibleOutsideFile()))));
|
2018-07-09 23:31:07 +08:00
|
|
|
}
|
|
|
|
|
2018-09-07 02:52:26 +08:00
|
|
|
TEST_F(SymbolCollectorTest, DeprecatedSymbols) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
void TestClangc() __attribute__((deprecated("", "")));
|
|
|
|
void TestClangd();
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /**/ "");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("TestClangc"), Deprecated()),
|
|
|
|
AllOf(QName("TestClangd"), Not(Deprecated()))));
|
|
|
|
}
|
|
|
|
|
2018-10-18 20:23:05 +08:00
|
|
|
TEST_F(SymbolCollectorTest, ImplementationDetail) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
#define DECL_NAME(x, y) x##_##y##_Decl
|
|
|
|
#define DECL(x, y) class DECL_NAME(x, y) {};
|
|
|
|
DECL(X, Y); // X_Y_Decl
|
|
|
|
|
|
|
|
class Public {};
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /**/ "");
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
AllOf(QName("X_Y_Decl"), ImplementationDetail()),
|
|
|
|
AllOf(QName("Public"), Not(ImplementationDetail()))));
|
|
|
|
}
|
|
|
|
|
2019-02-26 22:23:47 +08:00
|
|
|
TEST_F(SymbolCollectorTest, UsingDecl) {
|
|
|
|
const char *Header = R"(
|
|
|
|
void foo();
|
|
|
|
namespace std {
|
|
|
|
using ::foo;
|
|
|
|
})";
|
|
|
|
runSymbolCollector(Header, /**/ "");
|
|
|
|
EXPECT_THAT(Symbols, Contains(QName("std::foo")));
|
|
|
|
}
|
|
|
|
|
2019-04-11 00:26:58 +08:00
|
|
|
TEST_F(SymbolCollectorTest, CBuiltins) {
|
|
|
|
// In C, printf in stdio.h is a redecl of an implicit builtin.
|
|
|
|
const char *Header = R"(
|
|
|
|
extern int printf(const char*, ...);
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /**/ "", {"-xc"});
|
|
|
|
EXPECT_THAT(Symbols, Contains(QName("printf")));
|
|
|
|
}
|
|
|
|
|
2019-04-15 22:38:46 +08:00
|
|
|
TEST_F(SymbolCollectorTest, InvalidSourceLoc) {
|
|
|
|
const char *Header = R"(
|
|
|
|
void operator delete(void*)
|
|
|
|
__attribute__((__externally_visible__));)";
|
|
|
|
runSymbolCollector(Header, /**/ "");
|
|
|
|
EXPECT_THAT(Symbols, Contains(QName("operator delete")));
|
|
|
|
}
|
|
|
|
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|