[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 15:42:10 +00:00
|
|
|
//===-- SymbolCollectorTests.cpp -------------------------------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2018-01-31 12:56:51 +00:00
|
|
|
#include "Annotations.h"
|
2018-01-29 22:28:08 +00:00
|
|
|
#include "TestFS.h"
|
2018-06-21 12:12:26 +00: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 15:42:10 +00:00
|
|
|
#include "index/SymbolCollector.h"
|
2017-12-14 12:17:14 +00:00
|
|
|
#include "index/SymbolYAML.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 15:42:10 +00:00
|
|
|
#include "clang/Basic/FileManager.h"
|
|
|
|
#include "clang/Basic/FileSystemOptions.h"
|
|
|
|
#include "clang/Basic/VirtualFileSystem.h"
|
|
|
|
#include "clang/Frontend/CompilerInstance.h"
|
2017-12-13 12:53:16 +00: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 15:42:10 +00: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"
|
|
|
|
#include "gmock/gmock.h"
|
2017-12-13 12:53:16 +00: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 15:42:10 +00:00
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
|
2018-01-09 17:32:00 +00:00
|
|
|
using testing::AllOf;
|
[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 15:42:10 +00:00
|
|
|
using testing::Eq;
|
|
|
|
using testing::Field;
|
2018-01-09 17:32:00 +00:00
|
|
|
using testing::Not;
|
2017-12-13 12:53:16 +00:00
|
|
|
using testing::UnorderedElementsAre;
|
2018-01-09 10:44:09 +00:00
|
|
|
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 15:42:10 +00:00
|
|
|
|
|
|
|
// GMock helpers for matching Symbol.
|
2018-06-22 16:11:35 +00:00
|
|
|
MATCHER_P(Labeled, Label, "") {
|
|
|
|
return (arg.Name + arg.Signature).str() == Label;
|
|
|
|
}
|
|
|
|
MATCHER(HasReturnType, "") {
|
|
|
|
return arg.Detail && !arg.Detail->ReturnType.empty();
|
|
|
|
}
|
|
|
|
MATCHER_P(ReturnType, D, "") {
|
|
|
|
return arg.Detail && arg.Detail->ReturnType == D;
|
2018-01-09 17:32:00 +00:00
|
|
|
}
|
|
|
|
MATCHER_P(Doc, D, "") { return arg.Detail && arg.Detail->Documentation == D; }
|
|
|
|
MATCHER_P(Snippet, S, "") {
|
2018-06-22 16:11:35 +00:00
|
|
|
return (arg.Name + arg.CompletionSnippetSuffix).str() == S;
|
2018-01-09 17:32:00 +00:00
|
|
|
}
|
2018-01-19 22:18:21 +00:00
|
|
|
MATCHER_P(QName, Name, "") { return (arg.Scope + arg.Name).str() == Name; }
|
2018-02-06 16:10:35 +00:00
|
|
|
MATCHER_P(DeclURI, P, "") { return arg.CanonicalDeclaration.FileURI == P; }
|
[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 09:33:15 +00:00
|
|
|
MATCHER_P(DefURI, P, "") { return arg.Definition.FileURI == P; }
|
2018-02-16 14:15:55 +00:00
|
|
|
MATCHER_P(IncludeHeader, P, "") {
|
|
|
|
return arg.Detail && arg.Detail->IncludeHeader == P;
|
|
|
|
}
|
2018-04-13 08:30:39 +00:00
|
|
|
MATCHER_P(DeclRange, Pos, "") {
|
|
|
|
return std::tie(arg.CanonicalDeclaration.Start.Line,
|
|
|
|
arg.CanonicalDeclaration.Start.Column,
|
|
|
|
arg.CanonicalDeclaration.End.Line,
|
|
|
|
arg.CanonicalDeclaration.End.Column) ==
|
|
|
|
std::tie(Pos.start.line, Pos.start.character, Pos.end.line,
|
|
|
|
Pos.end.character);
|
|
|
|
}
|
|
|
|
MATCHER_P(DefRange, Pos, "") {
|
|
|
|
return std::tie(arg.Definition.Start.Line,
|
|
|
|
arg.Definition.Start.Column, arg.Definition.End.Line,
|
|
|
|
arg.Definition.End.Column) ==
|
|
|
|
std::tie(Pos.start.line, Pos.start.character, Pos.end.line,
|
|
|
|
Pos.end.character);
|
2018-02-09 14:42:01 +00:00
|
|
|
}
|
2018-03-12 14:49:09 +00:00
|
|
|
MATCHER_P(Refs, 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 14:01:40 +00:00
|
|
|
MATCHER_P(ForCodeCompletion, IsIndexedForCodeCompletion, "") {
|
|
|
|
return arg.IsIndexedForCodeCompletion == IsIndexedForCodeCompletion;
|
|
|
|
}
|
[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 15:42:10 +00:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
|
|
|
|
namespace {
|
2018-06-21 12:12:26 +00:00
|
|
|
|
|
|
|
class ShouldCollectSymbolTest : public ::testing::Test {
|
|
|
|
public:
|
|
|
|
void build(StringRef HeaderCode, StringRef Code = "") {
|
|
|
|
File.HeaderFilename = HeaderName;
|
|
|
|
File.Filename = FileName;
|
|
|
|
File.HeaderCode = HeaderCode;
|
|
|
|
File.Code = Code;
|
|
|
|
AST = File.build();
|
|
|
|
}
|
|
|
|
|
|
|
|
// build() must have been called.
|
|
|
|
bool shouldCollect(StringRef Name, bool Qualified = true) {
|
|
|
|
assert(AST.hasValue());
|
|
|
|
return SymbolCollector::shouldCollectSymbol(
|
|
|
|
Qualified ? findDecl(*AST, Name) : findAnyDecl(*AST, Name),
|
|
|
|
AST->getASTContext(), SymbolCollector::Options());
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
std::string HeaderName = "f.h";
|
|
|
|
std::string FileName = "f.cpp";
|
|
|
|
TestTU File;
|
|
|
|
Optional<ParsedAST> AST; // Initialized after build.
|
|
|
|
};
|
|
|
|
|
|
|
|
TEST_F(ShouldCollectSymbolTest, ShouldCollectSymbol) {
|
|
|
|
build(R"(
|
|
|
|
namespace nx {
|
|
|
|
class X{}
|
|
|
|
void f() { int Local; }
|
|
|
|
struct { int x } var;
|
|
|
|
namespace { class InAnonymous {}; }
|
|
|
|
}
|
|
|
|
)",
|
|
|
|
"class InMain {};");
|
|
|
|
auto AST = File.build();
|
|
|
|
EXPECT_TRUE(shouldCollect("nx"));
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::X"));
|
|
|
|
EXPECT_TRUE(shouldCollect("nx::f"));
|
|
|
|
|
|
|
|
EXPECT_FALSE(shouldCollect("InMain"));
|
|
|
|
EXPECT_FALSE(shouldCollect("Local", /*Qualified=*/false));
|
|
|
|
EXPECT_FALSE(shouldCollect("InAnonymous", /*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 15:42:10 +00:00
|
|
|
class SymbolIndexActionFactory : public tooling::FrontendActionFactory {
|
2017-12-13 12:53:16 +00:00
|
|
|
public:
|
2018-02-16 14:15:55 +00: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 15:42:10 +00:00
|
|
|
|
2018-02-27 15:54:41 +00:00
|
|
|
clang::FrontendAction *create() override {
|
2018-02-16 14:15:55 +00: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>
|
|
|
|
CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override {
|
|
|
|
if (PragmaHandler)
|
|
|
|
CI.getPreprocessor().addCommentHandler(PragmaHandler);
|
|
|
|
return WrapperFrontendAction::CreateASTConsumer(CI, InFile);
|
|
|
|
}
|
|
|
|
|
|
|
|
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 15:42:10 +00:00
|
|
|
index::IndexingOptions IndexOpts;
|
|
|
|
IndexOpts.SystemSymbolFilter =
|
|
|
|
index::IndexingOptions::SystemSymbolFilterKind::All;
|
|
|
|
IndexOpts.IndexFunctionLocals = false;
|
2018-01-10 14:57:58 +00:00
|
|
|
Collector = std::make_shared<SymbolCollector>(COpts);
|
2018-02-27 15:54:41 +00: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 15:42:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::shared_ptr<SymbolCollector> Collector;
|
2018-01-10 14:57:58 +00:00
|
|
|
SymbolCollector::Options COpts;
|
2018-02-16 14:15:55 +00: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 15:42:10 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class SymbolCollectorTest : public ::testing::Test {
|
|
|
|
public:
|
2018-02-06 16:10:35 +00:00
|
|
|
SymbolCollectorTest()
|
2018-02-16 14:15:55 +00:00
|
|
|
: InMemoryFileSystem(new vfs::InMemoryFileSystem),
|
|
|
|
TestHeaderName(testPath("symbol.h")),
|
2018-02-16 09:41:43 +00:00
|
|
|
TestFileName(testPath("symbol.cc")) {
|
2018-02-06 16:10:35 +00:00
|
|
|
TestHeaderURI = URI::createFile(TestHeaderName).toString();
|
|
|
|
TestFileURI = URI::createFile(TestFileName).toString();
|
|
|
|
}
|
|
|
|
|
2018-02-06 09:50:35 +00:00
|
|
|
bool runSymbolCollector(StringRef HeaderCode, StringRef MainCode,
|
|
|
|
const std::vector<std::string> &ExtraArgs = {}) {
|
[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 15:42:10 +00:00
|
|
|
llvm::IntrusiveRefCntPtr<FileManager> Files(
|
|
|
|
new FileManager(FileSystemOptions(), InMemoryFileSystem));
|
|
|
|
|
2018-02-16 14:15:55 +00: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 15:42:10 +00:00
|
|
|
|
2018-05-24 14:40:24 +00:00
|
|
|
std::vector<std::string> Args = {
|
[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 14:01:40 +00:00
|
|
|
"symbol_collector", "-fsyntax-only", "-xc++",
|
|
|
|
"-std=c++11", "-include", TestHeaderName};
|
2018-02-06 09:50:35 +00: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 14:01:40 +00: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 15:42:10 +00:00
|
|
|
tooling::ToolInvocation Invocation(
|
2018-02-06 09:50:35 +00:00
|
|
|
Args,
|
[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 15:42:10 +00:00
|
|
|
Factory->create(), Files.get(),
|
|
|
|
std::make_shared<PCHContainerOperations>());
|
|
|
|
|
2018-01-31 12:56:51 +00:00
|
|
|
InMemoryFileSystem->addFile(TestHeaderName, 0,
|
[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 15:42:10 +00:00
|
|
|
llvm::MemoryBuffer::getMemBuffer(HeaderCode));
|
2018-01-31 12:56:51 +00:00
|
|
|
InMemoryFileSystem->addFile(TestFileName, 0,
|
2018-02-09 14:42:01 +00: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 15:42:10 +00:00
|
|
|
Invocation.run();
|
|
|
|
Symbols = Factory->Collector->takeSymbols();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
2018-02-16 14:15:55 +00:00
|
|
|
llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem;
|
2018-02-06 16:10:35 +00: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 15:42:10 +00:00
|
|
|
SymbolSlab Symbols;
|
2018-01-10 14:57:58 +00:00
|
|
|
SymbolCollector::Options CollectorOpts;
|
2018-02-16 14:15:55 +00: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 15:42:10 +00:00
|
|
|
};
|
|
|
|
|
2018-01-10 14:57:58 +00: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 15:42:10 +00: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 14:01:40 +00: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 15:42:10 +00: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 14:01:40 +00: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 15:42:10 +00: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 14:01:40 +00: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 15:42:10 +00:00
|
|
|
void f1();
|
|
|
|
inline void f2() {}
|
2018-01-09 10:44:09 +00: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 09:33:15 +00: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 15:42:10 +00:00
|
|
|
namespace {
|
|
|
|
void ff() {} // ignore
|
|
|
|
}
|
2018-01-09 10:44:09 +00: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 15:42:10 +00:00
|
|
|
void f1() {}
|
2018-01-09 10:44:09 +00: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;
|
|
|
|
|
|
|
|
// FIXME: using declaration is not supported as the IndexAction will ignore
|
|
|
|
// implicit declarations (the implicit using shadow declaration) by default,
|
|
|
|
// and there is no way to customize this behavior at the moment.
|
|
|
|
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 15:42:10 +00: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 09:33:15 +00:00
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
2018-01-09 10:44:09 +00: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 14:01:40 +00: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)),
|
|
|
|
AllOf(QName("foo::baz"), ForCodeCompletion(true))}));
|
2018-01-29 15:13:29 +00:00
|
|
|
}
|
|
|
|
|
2018-03-09 13:25:29 +00:00
|
|
|
TEST_F(SymbolCollectorTest, Template) {
|
|
|
|
Annotations Header(R"(
|
|
|
|
// Template is indexed, specialization and instantiation is not.
|
[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 14:01:40 +00:00
|
|
|
template <class T> struct [[Tmpl]] {T $xdecl[[x]] = 0;};
|
2018-03-09 13:25:29 +00:00
|
|
|
template <> struct Tmpl<int> {};
|
|
|
|
extern template struct Tmpl<float>;
|
|
|
|
template struct Tmpl<double>;
|
|
|
|
)");
|
|
|
|
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 14:01:40 +00:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAreArray(
|
|
|
|
{AllOf(QName("Tmpl"), DeclRange(Header.range())),
|
|
|
|
AllOf(QName("Tmpl::x"), DeclRange(Header.range("xdecl")))}));
|
|
|
|
}
|
|
|
|
|
|
|
|
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
|
|
|
|
)";
|
|
|
|
TestFileName = "test.m";
|
|
|
|
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 13:25:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-09 14:42:01 +00:00
|
|
|
TEST_F(SymbolCollectorTest, Locations) {
|
|
|
|
Annotations Header(R"cpp(
|
|
|
|
// Declared in header, defined in main.
|
2018-02-13 09:53:50 +00:00
|
|
|
extern int $xdecl[[X]];
|
|
|
|
class $clsdecl[[Cls]];
|
|
|
|
void $printdecl[[print]]();
|
2018-02-09 14:42:01 +00:00
|
|
|
|
|
|
|
// Declared in header, defined nowhere.
|
2018-02-13 09:53:50 +00:00
|
|
|
extern int $zdecl[[Z]];
|
2018-04-13 08:30:39 +00:00
|
|
|
|
|
|
|
void $foodecl[[fo\
|
|
|
|
o]]();
|
2018-02-09 14:42:01 +00:00
|
|
|
)cpp");
|
|
|
|
Annotations Main(R"cpp(
|
2018-02-13 09:53:50 +00:00
|
|
|
int $xdef[[X]] = 42;
|
|
|
|
class $clsdef[[Cls]] {};
|
|
|
|
void $printdef[[print]]() {}
|
2018-02-09 14:42:01 +00:00
|
|
|
|
|
|
|
// Declared/defined in main only.
|
[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 09:33:15 +00:00
|
|
|
int Y;
|
2018-02-09 14:42:01 +00:00
|
|
|
)cpp");
|
|
|
|
runSymbolCollector(Header.code(), Main.code());
|
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAre(
|
2018-04-13 08:30:39 +00:00
|
|
|
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"))),
|
|
|
|
AllOf(QName("foo"), DeclRange(Header.range("foodecl")))
|
|
|
|
));
|
2018-02-09 14:42:01 +00:00
|
|
|
}
|
|
|
|
|
2018-03-12 14:49:09 +00: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 14:28:52 +00:00
|
|
|
#define GLOBAL_Z(name) Z name;
|
2018-03-12 14:49:09 +00:00
|
|
|
)";
|
|
|
|
const std::string Main = R"(
|
|
|
|
W* w = nullptr;
|
|
|
|
W* w2 = nullptr; // only one usage counts
|
|
|
|
X x();
|
|
|
|
class V;
|
|
|
|
V* v = nullptr; // Used, but not eligible for indexing.
|
|
|
|
class Y{}; // definition doesn't count as a reference
|
2018-04-09 14:28:52 +00:00
|
|
|
GLOBAL_Z(z); // Not a reference to Z, we don't spell the type.
|
2018-03-12 14:49:09 +00:00
|
|
|
)";
|
|
|
|
CollectorOpts.CountReferences = true;
|
|
|
|
runSymbolCollector(Header, Main);
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(AllOf(QName("W"), Refs(1)),
|
|
|
|
AllOf(QName("X"), Refs(1)),
|
|
|
|
AllOf(QName("Y"), Refs(0)),
|
|
|
|
AllOf(QName("Z"), Refs(0)), QName("y")));
|
|
|
|
}
|
|
|
|
|
2018-01-29 15:13:29 +00: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 09:33:15 +00:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
|
2018-01-29 15:13:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, SymbolRelativeWithFallback) {
|
2018-02-06 16:10:35 +00:00
|
|
|
TestHeaderName = "x.h";
|
|
|
|
TestFileName = "x.cpp";
|
2018-02-16 09:41:43 +00:00
|
|
|
TestHeaderURI = URI::createFile(testPath(TestHeaderName)).toString();
|
|
|
|
CollectorOpts.FallbackDir = testRoot();
|
2018-01-29 15:13:29 +00:00
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
2018-01-29 22:28:08 +00:00
|
|
|
EXPECT_THAT(Symbols,
|
2018-02-06 16:10:35 +00:00
|
|
|
UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, CustomURIScheme) {
|
|
|
|
// Use test URI scheme from URITests.cpp
|
|
|
|
CollectorOpts.URISchemes.insert(CollectorOpts.URISchemes.begin(), "unittest");
|
2018-06-15 08:55:00 +00:00
|
|
|
TestHeaderName = testPath("x.h");
|
|
|
|
TestFileName = testPath("x.cpp");
|
2018-02-06 16:10:35 +00:00
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
2018-06-15 08:55:00 +00:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI("unittest:///x.h"))));
|
2018-02-06 16:10:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, InvalidURIScheme) {
|
|
|
|
// Use test URI scheme from URITests.cpp
|
|
|
|
CollectorOpts.URISchemes = {"invalid"};
|
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(""))));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, FallbackToFileURI) {
|
|
|
|
// Use test URI scheme from URITests.cpp
|
|
|
|
CollectorOpts.URISchemes = {"invalid", "file"};
|
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
AllOf(QName("Foo"), DeclURI(TestHeaderURI))));
|
[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 15:42:10 +00:00
|
|
|
}
|
|
|
|
|
2018-01-19 09:35:55 +00: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 14:01:40 +00:00
|
|
|
Yellow
|
2018-01-19 09:35:55 +00: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 14:01:40 +00: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 09:35:55 +00: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 14:01:40 +00:00
|
|
|
TEST_F(SymbolCollectorTest, NamelessSymbols) {
|
2018-01-19 09:35:55 +00: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 14:01:40 +00:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo"),
|
|
|
|
QName("(anonymous struct)::a")));
|
2018-01-19 09:35:55 +00:00
|
|
|
}
|
|
|
|
|
2018-01-31 12:56:51 +00:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolFormedFromMacro) {
|
|
|
|
|
|
|
|
Annotations Header(R"(
|
|
|
|
#define FF(name) \
|
|
|
|
class name##_Test {};
|
|
|
|
|
2018-02-13 09:53:50 +00:00
|
|
|
$expansion[[FF]](abc);
|
2018-01-31 12:56:51 +00:00
|
|
|
|
|
|
|
#define FF2() \
|
2018-02-13 09:53:50 +00:00
|
|
|
class $spelling[[Test]] {};
|
2018-01-31 12:56:51 +00:00
|
|
|
|
|
|
|
FF2();
|
|
|
|
)");
|
|
|
|
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"");
|
2018-02-06 16:10:35 +00:00
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAre(
|
2018-04-13 08:30:39 +00:00
|
|
|
AllOf(QName("abc_Test"), DeclRange(Header.range("expansion")),
|
2018-02-06 16:10:35 +00:00
|
|
|
DeclURI(TestHeaderURI)),
|
2018-04-13 08:30:39 +00:00
|
|
|
AllOf(QName("Test"), DeclRange(Header.range("spelling")),
|
2018-02-06 16:10:35 +00:00
|
|
|
DeclURI(TestHeaderURI))));
|
2018-01-31 12:56:51 +00:00
|
|
|
}
|
|
|
|
|
2018-02-06 09:50:35 +00:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolFormedByCLI) {
|
|
|
|
Annotations Header(R"(
|
|
|
|
#ifdef NAME
|
2018-02-13 09:53:50 +00:00
|
|
|
class $expansion[[NAME]] {};
|
2018-02-06 09:50:35 +00:00
|
|
|
#endif
|
|
|
|
)");
|
|
|
|
|
|
|
|
runSymbolCollector(Header.code(), /*Main=*/"",
|
|
|
|
/*ExtraArgs=*/{"-DNAME=name"});
|
2018-02-09 14:42:01 +00:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(AllOf(
|
2018-04-13 08:30:39 +00:00
|
|
|
QName("name"),
|
|
|
|
DeclRange(Header.range("expansion")),
|
2018-02-09 14:42:01 +00:00
|
|
|
DeclURI(TestHeaderURI))));
|
2018-02-06 09:50:35 +00:00
|
|
|
}
|
|
|
|
|
2018-01-10 14:57:58 +00:00
|
|
|
TEST_F(SymbolCollectorTest, IgnoreSymbolsInMainFile) {
|
|
|
|
const std::string Header = R"(
|
|
|
|
class Foo {};
|
|
|
|
void f1();
|
|
|
|
inline void f2() {}
|
|
|
|
)";
|
|
|
|
const std::string Main = R"(
|
|
|
|
namespace {
|
|
|
|
void ff() {} // ignore
|
|
|
|
}
|
|
|
|
void main_f() {} // ignore
|
|
|
|
void f1() {}
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, Main);
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(QName("Foo"), QName("f1"), QName("f2")));
|
|
|
|
}
|
|
|
|
|
[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 14:01:40 +00:00
|
|
|
TEST_F(SymbolCollectorTest, ClassMembers) {
|
2018-01-10 14:57:58 +00:00
|
|
|
const std::string Header = R"(
|
|
|
|
class Foo {
|
|
|
|
void f() {}
|
|
|
|
void g();
|
|
|
|
static void sf() {}
|
|
|
|
static void ssf();
|
|
|
|
static int x;
|
|
|
|
};
|
|
|
|
)";
|
2018-01-09 17:32:00 +00:00
|
|
|
const std::string Main = R"(
|
2018-01-10 14:57:58 +00:00
|
|
|
void Foo::g() {}
|
|
|
|
void Foo::ssf() {}
|
|
|
|
)";
|
|
|
|
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 14:01:40 +00:00
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(QName("Foo"), QName("Foo::f"),
|
|
|
|
QName("Foo::g"), QName("Foo::sf"),
|
|
|
|
QName("Foo::ssf"), QName("Foo::x")));
|
2018-01-10 14:57:58 +00:00
|
|
|
}
|
|
|
|
|
2018-02-02 10:31:42 +00: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-02 17:01:36 +00:00
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(QName("na"), QName("Foo"),
|
|
|
|
QName("na::Bar")));
|
2018-02-02 10:31:42 +00: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 14:57:58 +00:00
|
|
|
TEST_F(SymbolCollectorTest, SymbolWithDocumentation) {
|
|
|
|
const std::string Header = R"(
|
2018-01-09 17:32:00 +00:00
|
|
|
namespace nx {
|
|
|
|
/// Foo comment.
|
|
|
|
int ff(int x, double y) { return 0; }
|
|
|
|
}
|
|
|
|
)";
|
2018-01-10 14:57:58 +00:00
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
2018-05-16 12:32:44 +00:00
|
|
|
EXPECT_THAT(
|
|
|
|
Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("nx"), AllOf(QName("nx::ff"), Labeled("ff(int x, double y)"),
|
2018-06-22 16:11:35 +00:00
|
|
|
ReturnType("int"), Doc("Foo comment."))));
|
2018-01-09 17:32:00 +00:00
|
|
|
}
|
|
|
|
|
2018-06-22 16:11:35 +00:00
|
|
|
TEST_F(SymbolCollectorTest, Snippet) {
|
2018-01-10 14:57:58 +00:00
|
|
|
const std::string Header = R"(
|
2018-01-09 17:32:00 +00:00
|
|
|
namespace nx {
|
|
|
|
void f() {}
|
|
|
|
int ff(int x, double y) { return 0; }
|
|
|
|
}
|
|
|
|
)";
|
2018-01-10 14:57:58 +00:00
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
2018-06-22 16:11:35 +00: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-09 17:32:00 +00:00
|
|
|
}
|
|
|
|
|
2017-12-14 12:17:14 +00:00
|
|
|
TEST_F(SymbolCollectorTest, YAMLConversions) {
|
|
|
|
const std::string YAML1 = R"(
|
|
|
|
---
|
|
|
|
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
|
2017-12-19 11:37:40 +00:00
|
|
|
Name: 'Foo1'
|
2018-01-19 22:18:21 +00:00
|
|
|
Scope: 'clang::'
|
2017-12-14 12:17:14 +00:00
|
|
|
SymInfo:
|
|
|
|
Kind: Function
|
|
|
|
Lang: Cpp
|
|
|
|
CanonicalDeclaration:
|
2018-02-06 16:10:35 +00:00
|
|
|
FileURI: file:///path/foo.h
|
2018-04-13 08:30:39 +00:00
|
|
|
Start:
|
|
|
|
Line: 1
|
|
|
|
Column: 0
|
|
|
|
End:
|
|
|
|
Line: 1
|
|
|
|
Column: 1
|
[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 14:01:40 +00:00
|
|
|
IsIndexedForCodeCompletion: true
|
2018-01-09 17:32:00 +00:00
|
|
|
Detail:
|
|
|
|
Documentation: 'Foo doc'
|
2018-06-22 16:11:35 +00:00
|
|
|
ReturnType: 'int'
|
2017-12-14 12:17:14 +00:00
|
|
|
...
|
|
|
|
)";
|
|
|
|
const std::string YAML2 = R"(
|
|
|
|
---
|
|
|
|
ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858
|
2017-12-19 11:37:40 +00:00
|
|
|
Name: 'Foo2'
|
2018-01-19 22:18:21 +00:00
|
|
|
Scope: 'clang::'
|
2017-12-14 12:17:14 +00:00
|
|
|
SymInfo:
|
|
|
|
Kind: Function
|
|
|
|
Lang: Cpp
|
|
|
|
CanonicalDeclaration:
|
2018-02-06 16:10:35 +00:00
|
|
|
FileURI: file:///path/bar.h
|
2018-04-13 08:30:39 +00:00
|
|
|
Start:
|
|
|
|
Line: 1
|
|
|
|
Column: 0
|
|
|
|
End:
|
|
|
|
Line: 1
|
|
|
|
Column: 1
|
[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 14:01:40 +00:00
|
|
|
IsIndexedForCodeCompletion: false
|
2018-06-22 16:11:35 +00:00
|
|
|
Signature: '-sig'
|
|
|
|
CompletionSnippetSuffix: '-snippet'
|
2017-12-14 12:17:14 +00:00
|
|
|
...
|
|
|
|
)";
|
|
|
|
|
2018-02-09 14:42:01 +00:00
|
|
|
auto Symbols1 = SymbolsFromYAML(YAML1);
|
2018-04-13 08:30:39 +00:00
|
|
|
|
2018-02-06 16:10:35 +00:00
|
|
|
EXPECT_THAT(Symbols1,
|
2018-06-22 16:11:35 +00:00
|
|
|
UnorderedElementsAre(AllOf(QName("clang::Foo1"), Labeled("Foo1"),
|
|
|
|
Doc("Foo doc"), ReturnType("int"),
|
|
|
|
DeclURI("file:///path/foo.h"),
|
|
|
|
ForCodeCompletion(true))));
|
2018-02-09 14:42:01 +00:00
|
|
|
auto Symbols2 = SymbolsFromYAML(YAML2);
|
2018-06-22 16:11:35 +00:00
|
|
|
EXPECT_THAT(Symbols2, UnorderedElementsAre(AllOf(
|
|
|
|
QName("clang::Foo2"), Labeled("Foo2-sig"),
|
|
|
|
Not(HasReturnType()), DeclURI("file:///path/bar.h"),
|
|
|
|
ForCodeCompletion(false))));
|
2017-12-14 12:17:14 +00:00
|
|
|
|
2018-02-09 14:42:01 +00:00
|
|
|
std::string ConcatenatedYAML;
|
|
|
|
{
|
|
|
|
llvm::raw_string_ostream OS(ConcatenatedYAML);
|
|
|
|
SymbolsToYAML(Symbols1, OS);
|
|
|
|
SymbolsToYAML(Symbols2, OS);
|
|
|
|
}
|
|
|
|
auto ConcatenatedSymbols = SymbolsFromYAML(ConcatenatedYAML);
|
2017-12-14 12:17:14 +00:00
|
|
|
EXPECT_THAT(ConcatenatedSymbols,
|
|
|
|
UnorderedElementsAre(QName("clang::Foo1"),
|
|
|
|
QName("clang::Foo2")));
|
|
|
|
}
|
|
|
|
|
2018-02-16 14:15:55 +00:00
|
|
|
TEST_F(SymbolCollectorTest, IncludeHeaderSameAsFileURI) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(AllOf(QName("Foo"), DeclURI(TestHeaderURI),
|
[clangd] Not collect include headers for dynamic index for now.
Summary:
The new behaviors introduced by this patch:
o When include collection is enabled, we always set IncludeHeader field in Symbol
even if it's the same as FileURI in decl.
o Disable include collection in FileIndex which is currently only used to build
dynamic index. We should revisit when we actually want to use FileIndex to global
index.
o Code-completion only uses IncludeHeader to insert headers but not FileURI in
CanonicalDeclaration. This ensures that inserted headers are always canonicalized.
Note that include insertion can still be triggered for symbols that are already
included if they are merged from dynamic index and static index, but we would
only use includes that are already canonicalized (e.g. from static index).
Reason for change:
Collecting header includes in dynamic index enables inserting includes for headers
that are not indexed but opened in the editor. Comparing to inserting includes for
symbols in global/static index, this is nice-to-have but would probably require
non-trivial amount of work to get right. For example:
o Currently it's not easy to fully support CanonicalIncludes in dynamic index, given the way
we run dynamic index.
o It's also harder to reason about the correctness of include canonicalization for dynamic index
(i.e. symbols in the current file/TU) than static index where symbols are collected
offline and sanity check is possible before shipping to production.
o We have less control/flexibility over symbol info in the dynamic index
(e.g. URIs, path normalization), which could be used to help make decision when inserting includes.
As header collection (especially canonicalization) is relatively new, and enabling
it for dynamic index would immediately affect current users with only dynamic
index support, I propose we disable it for dynamic index for now to avoid
compromising other hot features like code completion and only support it for
static index where include insertion would likely to bring more value.
Reviewers: ilya-biryukov, sammccall, hokein
Subscribers: klimek, jkorous-apple, cfe-commits
Differential Revision: https://reviews.llvm.org/D43550
llvm-svn: 325764
2018-02-22 10:14:05 +00:00
|
|
|
IncludeHeader(TestHeaderURI))));
|
2018-02-16 14:15:55 +00:00
|
|
|
}
|
|
|
|
|
2018-04-10 13:14:03 +00:00
|
|
|
#ifndef _WIN32
|
2018-02-16 14:15:55 +00:00
|
|
|
TEST_F(SymbolCollectorTest, CanonicalSTLHeader) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
addSystemHeadersMapping(&Includes);
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
// bits/basic_string.h$ should be mapped to <string>
|
|
|
|
TestHeaderName = "/nasty/bits/basic_string.h";
|
|
|
|
TestFileName = "/nasty/bits/basic_string.cpp";
|
|
|
|
TestHeaderURI = URI::createFile(TestHeaderName).toString();
|
|
|
|
runSymbolCollector("class string {};", /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("string"),
|
|
|
|
DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader("<string>"))));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-01 18:06:40 +00:00
|
|
|
TEST_F(SymbolCollectorTest, STLiosfwd) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
addSystemHeadersMapping(&Includes);
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
// Symbols from <iosfwd> should be mapped individually.
|
|
|
|
TestHeaderName = testPath("iosfwd");
|
|
|
|
TestFileName = testPath("iosfwd.cpp");
|
|
|
|
std::string Header = R"(
|
|
|
|
namespace std {
|
|
|
|
class no_map {};
|
|
|
|
class ios {};
|
|
|
|
class ostream {};
|
|
|
|
class filebuf {};
|
|
|
|
} // namespace std
|
|
|
|
)";
|
|
|
|
runSymbolCollector(Header, /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols,
|
|
|
|
UnorderedElementsAre(
|
|
|
|
QName("std"),
|
|
|
|
AllOf(QName("std::no_map"), IncludeHeader("<iosfwd>")),
|
|
|
|
AllOf(QName("std::ios"), IncludeHeader("<ios>")),
|
|
|
|
AllOf(QName("std::ostream"), IncludeHeader("<ostream>")),
|
|
|
|
AllOf(QName("std::filebuf"), IncludeHeader("<fstream>"))));
|
|
|
|
}
|
|
|
|
|
2018-02-16 14:15:55 +00: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 08:33:30 +00: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 14:40:24 +00:00
|
|
|
TEST_F(SymbolCollectorTest, SkipIncFileWhenCanonicalizeHeaders) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
Includes.addMapping(TestHeaderName, "<canonical>");
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
auto IncFile = testPath("test.inc");
|
|
|
|
auto IncURI = URI::createFile(IncFile).toString();
|
|
|
|
InMemoryFileSystem->addFile(IncFile, 0,
|
|
|
|
llvm::MemoryBuffer::getMemBuffer("class X {};"));
|
|
|
|
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;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
TestFileName = testPath("main.h");
|
|
|
|
TestFileURI = URI::createFile(TestFileName).toString();
|
|
|
|
auto IncFile = testPath("test.inc");
|
|
|
|
auto IncURI = URI::createFile(IncFile).toString();
|
|
|
|
InMemoryFileSystem->addFile(IncFile, 0,
|
|
|
|
llvm::MemoryBuffer::getMemBuffer("class X {};"));
|
|
|
|
runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
|
|
|
|
/*ExtraArgs=*/{"-I", testRoot()});
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
|
|
|
|
IncludeHeader(TestFileURI))));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, MainFileIsHeaderWithoutExtensionWhenSkipIncFile) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
TestFileName = testPath("no_ext_main");
|
|
|
|
TestFileURI = URI::createFile(TestFileName).toString();
|
|
|
|
auto IncFile = testPath("test.inc");
|
|
|
|
auto IncURI = URI::createFile(IncFile).toString();
|
|
|
|
InMemoryFileSystem->addFile(IncFile, 0,
|
|
|
|
llvm::MemoryBuffer::getMemBuffer("class X {};"));
|
|
|
|
runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
|
|
|
|
/*ExtraArgs=*/{"-I", testRoot()});
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
|
|
|
|
IncludeHeader(TestFileURI))));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, FallbackToIncFileWhenIncludingFileIsCC) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
CanonicalIncludes Includes;
|
|
|
|
CollectorOpts.Includes = &Includes;
|
|
|
|
auto IncFile = testPath("test.inc");
|
|
|
|
auto IncURI = URI::createFile(IncFile).toString();
|
|
|
|
InMemoryFileSystem->addFile(IncFile, 0,
|
|
|
|
llvm::MemoryBuffer::getMemBuffer("class X {};"));
|
|
|
|
runSymbolCollector("", /*Main=*/"#include \"test.inc\"",
|
|
|
|
/*ExtraArgs=*/{"-I", testRoot()});
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), DeclURI(IncURI),
|
|
|
|
IncludeHeader(IncURI))));
|
|
|
|
}
|
|
|
|
|
[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 09:33:15 +00:00
|
|
|
TEST_F(SymbolCollectorTest, AvoidUsingFwdDeclsAsCanonicalDecls) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
Annotations Header(R"(
|
|
|
|
// 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 14:01:40 +00: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 09:33:15 +00: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 14:01:40 +00: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 09:33:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_F(SymbolCollectorTest, ClassForwardDeclarationIsCanonical) {
|
|
|
|
CollectorOpts.CollectIncludePath = true;
|
|
|
|
runSymbolCollector(/*Header=*/"class X;", /*Main=*/"class X {};");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(
|
|
|
|
QName("X"), DeclURI(TestHeaderURI),
|
|
|
|
IncludeHeader(TestHeaderURI), DefURI(TestFileURI))));
|
|
|
|
}
|
|
|
|
|
2018-04-30 11:40:02 +00: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 11:31:55 +00: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);
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(AllOf(QName("X"), Refs(1)),
|
|
|
|
AllOf(QName("Y"), Refs(1))));
|
|
|
|
}
|
|
|
|
|
2018-07-05 06:20:41 +00:00
|
|
|
TEST_F(SymbolCollectorTest, Origin) {
|
|
|
|
CollectorOpts.Origin = SymbolOrigin::Static;
|
|
|
|
runSymbolCollector("class Foo {};", /*Main=*/"");
|
|
|
|
EXPECT_THAT(Symbols, UnorderedElementsAre(
|
|
|
|
Field(&Symbol::Origin, SymbolOrigin::Static)));
|
|
|
|
}
|
|
|
|
|
[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 15:42:10 +00:00
|
|
|
} // namespace
|
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|