[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
//===--- Index.cpp -----------------------------------------------*- C++-*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "Index.h"
|
2017-12-14 20:17:14 +08:00
|
|
|
#include "llvm/ADT/StringExtras.h"
|
[clangd] Support multiple #include headers in one symbol.
Summary:
Currently, a symbol can have only one #include header attached, which
might not work well if the symbol can be imported via different #includes depending
on where it's used. This patch stores multiple #include headers (with # references)
for each symbol, so that CodeCompletion can decide which include to insert.
In this patch, code completion simply picks the most popular include as the default inserted header. We also return all possible includes and their edits in the `CodeCompletion` results.
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: mgrang, ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51291
llvm-svn: 341304
2018-09-03 18:18:21 +08:00
|
|
|
#include "llvm/ADT/StringRef.h"
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
#include "llvm/Support/Error.h"
|
2017-12-15 05:22:03 +08:00
|
|
|
#include "llvm/Support/SHA1.h"
|
2018-02-09 22:42:01 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
2017-12-24 03:38:03 +08:00
|
|
|
using namespace llvm;
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
|
2018-02-09 22:42:01 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const SymbolLocation &L) {
|
|
|
|
if (!L)
|
|
|
|
return OS << "(none)";
|
2018-04-13 16:30:39 +08:00
|
|
|
return OS << L.FileURI << "[" << L.Start.Line << ":" << L.Start.Column << "-"
|
|
|
|
<< L.End.Line << ":" << L.End.Column << ")";
|
2018-02-09 22:42:01 +08:00
|
|
|
}
|
|
|
|
|
2017-12-24 03:38:03 +08:00
|
|
|
SymbolID::SymbolID(StringRef USR)
|
|
|
|
: HashValue(SHA1::hash(arrayRefFromStringRef(USR))) {}
|
2017-12-14 20:17:14 +08:00
|
|
|
|
2017-12-24 03:38:03 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const SymbolID &ID) {
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
return OS << toHex(ID.raw());
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
SymbolID SymbolID::fromRaw(llvm::StringRef Raw) {
|
|
|
|
SymbolID ID;
|
|
|
|
assert(Raw.size() == RawSize);
|
|
|
|
memcpy(ID.HashValue.data(), Raw.data(), RawSize);
|
|
|
|
return ID;
|
2018-04-25 23:27:09 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
std::string SymbolID::str() const { return toHex(raw()); }
|
|
|
|
|
2018-09-19 03:00:59 +08:00
|
|
|
llvm::Expected<SymbolID> SymbolID::fromStr(llvm::StringRef Str) {
|
|
|
|
if (Str.size() != RawSize * 2)
|
|
|
|
return createStringError(llvm::inconvertibleErrorCode(), "Bad ID length");
|
|
|
|
for (char C : Str)
|
|
|
|
if (!isHexDigit(C))
|
|
|
|
return createStringError(llvm::inconvertibleErrorCode(), "Bad hex ID");
|
|
|
|
return fromRaw(fromHex(Str));
|
2017-12-14 20:17:14 +08:00
|
|
|
}
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
|
2018-07-05 14:20:41 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, SymbolOrigin O) {
|
|
|
|
if (O == SymbolOrigin::Unknown)
|
|
|
|
return OS << "unknown";
|
|
|
|
constexpr static char Sigils[] = "ADSM4567";
|
|
|
|
for (unsigned I = 0; I < sizeof(Sigils); ++I)
|
2018-07-06 19:50:49 +08:00
|
|
|
if (static_cast<uint8_t>(O) & 1u << I)
|
2018-07-05 14:20:41 +08:00
|
|
|
OS << Sigils[I];
|
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
2018-09-07 02:52:26 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, Symbol::SymbolFlag F) {
|
|
|
|
if (F == Symbol::None)
|
|
|
|
return OS << "None";
|
|
|
|
std::string s;
|
|
|
|
if (F & Symbol::Deprecated)
|
|
|
|
s += "deprecated|";
|
|
|
|
if (F & Symbol::IndexedForCodeCompletion)
|
|
|
|
s += "completion|";
|
|
|
|
return OS << StringRef(s).rtrim('|');
|
|
|
|
}
|
|
|
|
|
2018-02-09 22:42:01 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) {
|
|
|
|
return OS << S.Scope << S.Name;
|
|
|
|
}
|
|
|
|
|
2018-09-04 23:45:56 +08:00
|
|
|
float quality(const Symbol &S) {
|
2018-05-03 22:53:02 +08:00
|
|
|
// This avoids a sharp gradient for tail symbols, and also neatly avoids the
|
|
|
|
// question of whether 0 references means a bad symbol or missing data.
|
|
|
|
if (S.References < 3)
|
|
|
|
return 1;
|
|
|
|
return std::log(S.References);
|
|
|
|
}
|
|
|
|
|
2017-12-24 03:38:03 +08:00
|
|
|
SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
|
|
|
|
auto It = std::lower_bound(Symbols.begin(), Symbols.end(), ID,
|
|
|
|
[](const Symbol &S, const SymbolID &I) {
|
|
|
|
return S.ID < I;
|
|
|
|
});
|
|
|
|
if (It != Symbols.end() && It->ID == ID)
|
|
|
|
return It;
|
|
|
|
return Symbols.end();
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
}
|
|
|
|
|
2017-12-24 03:38:03 +08:00
|
|
|
// Copy the underlying data of the symbol into the owned arena.
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
|
|
|
|
visitStrings(S, [&](StringRef &V) { V = Strings.save(V); });
|
2017-12-24 03:38:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void SymbolSlab::Builder::insert(const Symbol &S) {
|
|
|
|
auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
|
|
|
|
if (R.second) {
|
|
|
|
Symbols.push_back(S);
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
own(Symbols.back(), UniqueStrings);
|
2017-12-24 03:38:03 +08:00
|
|
|
} else {
|
|
|
|
auto &Copy = Symbols[R.first->second] = S;
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
own(Copy, UniqueStrings);
|
2017-12-24 03:38:03 +08:00
|
|
|
}
|
|
|
|
}
|
2017-12-21 22:58:44 +08:00
|
|
|
|
2017-12-24 03:38:03 +08:00
|
|
|
SymbolSlab SymbolSlab::Builder::build() && {
|
|
|
|
Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
|
|
|
|
// Sort symbols so the slab can binary search over them.
|
|
|
|
std::sort(Symbols.begin(), Symbols.end(),
|
|
|
|
[](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
|
|
|
|
// We may have unused strings from overwritten symbols. Build a new arena.
|
|
|
|
BumpPtrAllocator NewArena;
|
2018-08-20 17:47:12 +08:00
|
|
|
llvm::UniqueStringSaver Strings(NewArena);
|
2017-12-24 03:38:03 +08:00
|
|
|
for (auto &S : Symbols)
|
[clangd] Define a compact binary serialization fomat for symbol slab/index.
Summary:
This is intended to replace the current YAML format for general use.
It's ~10x more compact than YAML, and ~40% more compact than gzipped YAML:
llvmidx.riff = 20M, llvmidx.yaml = 272M, llvmidx.yaml.gz = 32M
It's also simpler/faster to read and write.
The format is a RIFF container (chunks of (type, size, data)) with:
- a compressed string table
- simple binary encoding of symbols (with varints for compactness)
It can be extended to include occurrences, Dex posting lists, etc.
There's no rich backwards-compatibility scheme, but a version number is included
so we can detect incompatible files and do ad-hoc back-compat.
Alternatives considered:
- compressed YAML or JSON: bulky and slow to load
- llvm bitstream: confusing model and libraries are hard to use. My attempt
produced slightly larger files, and the code was longer and slower.
- protobuf or similar: would be really nice (esp for back-compat) but the
dependency is a big hassle
- ad-hoc binary format without a container: it seems clear we're going
to add posting lists and occurrences here, and that they will benefit
from sharing a string table. The container makes it easy to debug
these pieces in isolation, and make them optional.
Reviewers: ioeric
Subscribers: mgorny, ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51585
llvm-svn: 341375
2018-09-05 00:16:50 +08:00
|
|
|
own(S, Strings);
|
2017-12-24 03:38:03 +08:00
|
|
|
return SymbolSlab(std::move(NewArena), std::move(Symbols));
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
}
|
|
|
|
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
raw_ostream &operator<<(raw_ostream &OS, RefKind K) {
|
|
|
|
if (K == RefKind::Unknown)
|
2018-08-31 20:54:13 +08:00
|
|
|
return OS << "Unknown";
|
|
|
|
static const std::vector<const char *> Messages = {"Decl", "Def", "Ref"};
|
|
|
|
bool VisitedOnce = false;
|
|
|
|
for (unsigned I = 0; I < Messages.size(); ++I) {
|
|
|
|
if (static_cast<uint8_t>(K) & 1u << I) {
|
|
|
|
if (VisitedOnce)
|
|
|
|
OS << ", ";
|
|
|
|
OS << Messages[I];
|
|
|
|
VisitedOnce = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OS;
|
|
|
|
}
|
|
|
|
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Ref &R) {
|
|
|
|
return OS << R.Location << ":" << R.Kind;
|
2018-08-31 20:54:13 +08:00
|
|
|
}
|
|
|
|
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
void RefSlab::Builder::insert(const SymbolID &ID, const Ref &S) {
|
|
|
|
auto &M = Refs[ID];
|
|
|
|
M.push_back(S);
|
|
|
|
M.back().Location.FileURI = UniqueStrings.save(M.back().Location.FileURI);
|
2018-08-31 20:54:13 +08:00
|
|
|
}
|
|
|
|
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
RefSlab RefSlab::Builder::build() && {
|
|
|
|
// We can reuse the arena, as it only has unique strings and we need them all.
|
|
|
|
// Reallocate refs on the arena to reduce waste and indirections when reading.
|
|
|
|
std::vector<std::pair<SymbolID, ArrayRef<Ref>>> Result;
|
|
|
|
Result.reserve(Refs.size());
|
|
|
|
for (auto &Sym : Refs) {
|
|
|
|
auto &SymRefs = Sym.second;
|
|
|
|
std::sort(SymRefs.begin(), SymRefs.end());
|
|
|
|
// TODO: do we really need to dedup?
|
|
|
|
SymRefs.erase(std::unique(SymRefs.begin(), SymRefs.end()), SymRefs.end());
|
|
|
|
|
|
|
|
auto *Array = Arena.Allocate<Ref>(SymRefs.size());
|
|
|
|
std::uninitialized_copy(SymRefs.begin(), SymRefs.end(), Array);
|
|
|
|
Result.emplace_back(Sym.first, ArrayRef<Ref>(Array, SymRefs.size()));
|
2018-08-31 20:54:13 +08:00
|
|
|
}
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
return RefSlab(std::move(Result), std::move(Arena));
|
2018-08-31 20:54:13 +08:00
|
|
|
}
|
|
|
|
|
[clangd] Factor out the data-swapping functionality from MemIndex/DexIndex.
Summary:
This is now handled by a wrapper class SwapIndex, so MemIndex/DexIndex can be
immutable and focus on their job.
Old and busted:
I have a MemIndex, which holds a shared_ptr<vector<Symbol*>>, which keeps the
symbol slab alive. I update by calling build(shared_ptr<vector<Symbol*>>).
New hotness: I have a SwapIndex, which holds a unique_ptr<SymbolIndex>, which
holds a MemIndex, which holds a shared_ptr<void>, which keeps backing
data alive.
I update by building a new MemIndex and calling SwapIndex::reset().
Reviewers: kbobyrev, ioeric
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51422
llvm-svn: 341318
2018-09-03 22:37:43 +08:00
|
|
|
void SwapIndex::reset(std::unique_ptr<SymbolIndex> Index) {
|
|
|
|
// Keep the old index alive, so we don't destroy it under lock (may be slow).
|
|
|
|
std::shared_ptr<SymbolIndex> Pin;
|
|
|
|
{
|
|
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
|
|
Pin = std::move(this->Index);
|
|
|
|
this->Index = std::move(Index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
std::shared_ptr<SymbolIndex> SwapIndex::snapshot() const {
|
|
|
|
std::lock_guard<std::mutex> Lock(Mutex);
|
|
|
|
return Index;
|
|
|
|
}
|
|
|
|
|
2018-09-10 19:51:05 +08:00
|
|
|
bool fromJSON(const llvm::json::Value &Parameters, FuzzyFindRequest &Request) {
|
|
|
|
json::ObjectMapper O(Parameters);
|
2018-09-13 22:27:03 +08:00
|
|
|
int64_t Limit;
|
2018-09-10 19:51:05 +08:00
|
|
|
bool OK =
|
|
|
|
O && O.map("Query", Request.Query) && O.map("Scopes", Request.Scopes) &&
|
2018-09-13 22:27:03 +08:00
|
|
|
O.map("Limit", Limit) &&
|
2018-09-10 19:51:05 +08:00
|
|
|
O.map("RestrictForCodeCompletion", Request.RestrictForCodeCompletion) &&
|
2018-09-11 18:31:38 +08:00
|
|
|
O.map("ProximityPaths", Request.ProximityPaths);
|
2018-09-13 22:27:03 +08:00
|
|
|
if (OK && Limit <= std::numeric_limits<uint32_t>::max())
|
|
|
|
Request.Limit = Limit;
|
2018-09-10 19:51:05 +08:00
|
|
|
return OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
llvm::json::Value toJSON(const FuzzyFindRequest &Request) {
|
2018-09-11 18:31:38 +08:00
|
|
|
return json::Object{
|
2018-09-10 19:51:05 +08:00
|
|
|
{"Query", Request.Query},
|
|
|
|
{"Scopes", json::Array{Request.Scopes}},
|
2018-09-13 22:27:03 +08:00
|
|
|
{"Limit", Request.Limit},
|
2018-09-10 19:51:05 +08:00
|
|
|
{"RestrictForCodeCompletion", Request.RestrictForCodeCompletion},
|
|
|
|
{"ProximityPaths", json::Array{Request.ProximityPaths}},
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
[clangd] Factor out the data-swapping functionality from MemIndex/DexIndex.
Summary:
This is now handled by a wrapper class SwapIndex, so MemIndex/DexIndex can be
immutable and focus on their job.
Old and busted:
I have a MemIndex, which holds a shared_ptr<vector<Symbol*>>, which keeps the
symbol slab alive. I update by calling build(shared_ptr<vector<Symbol*>>).
New hotness: I have a SwapIndex, which holds a unique_ptr<SymbolIndex>, which
holds a MemIndex, which holds a shared_ptr<void>, which keeps backing
data alive.
I update by building a new MemIndex and calling SwapIndex::reset().
Reviewers: kbobyrev, ioeric
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51422
llvm-svn: 341318
2018-09-03 22:37:43 +08:00
|
|
|
bool SwapIndex::fuzzyFind(const FuzzyFindRequest &R,
|
|
|
|
llvm::function_ref<void(const Symbol &)> CB) const {
|
|
|
|
return snapshot()->fuzzyFind(R, CB);
|
|
|
|
}
|
|
|
|
void SwapIndex::lookup(const LookupRequest &R,
|
|
|
|
llvm::function_ref<void(const Symbol &)> CB) const {
|
|
|
|
return snapshot()->lookup(R, CB);
|
|
|
|
}
|
[clangd] SymbolOccurrences -> Refs and cleanup
Summary:
A few things that I noticed while merging the SwapIndex patch:
- SymbolOccurrences and particularly SymbolOccurrenceSlab are unwieldy names,
and these names appear *a lot*. Ref, RefSlab, etc seem clear enough
and read/format much better.
- The asymmetry between SymbolSlab and RefSlab (build() vs freeze()) is
confusing and irritating, and doesn't even save much code.
Avoiding RefSlab::Builder was my idea, but it was a bad one; add it.
- DenseMap<SymbolID, ArrayRef<Ref>> seems like a reasonable compromise for
constructing MemIndex - and means many less wasted allocations than the
current DenseMap<SymbolID, vector<Ref*>> for FileIndex, and none for
slabs.
- RefSlab::find() is not actually used for anything, so we can throw
away the DenseMap and keep the representation much more compact.
- A few naming/consistency fixes: e.g. Slabs,Refs -> Symbols,Refs.
Reviewers: ioeric
Subscribers: ilya-biryukov, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51605
llvm-svn: 341368
2018-09-04 22:39:56 +08:00
|
|
|
void SwapIndex::refs(const RefsRequest &R,
|
|
|
|
llvm::function_ref<void(const Ref &)> CB) const {
|
|
|
|
return snapshot()->refs(R, CB);
|
[clangd] Factor out the data-swapping functionality from MemIndex/DexIndex.
Summary:
This is now handled by a wrapper class SwapIndex, so MemIndex/DexIndex can be
immutable and focus on their job.
Old and busted:
I have a MemIndex, which holds a shared_ptr<vector<Symbol*>>, which keeps the
symbol slab alive. I update by calling build(shared_ptr<vector<Symbol*>>).
New hotness: I have a SwapIndex, which holds a unique_ptr<SymbolIndex>, which
holds a MemIndex, which holds a shared_ptr<void>, which keeps backing
data alive.
I update by building a new MemIndex and calling SwapIndex::reset().
Reviewers: kbobyrev, ioeric
Subscribers: ilya-biryukov, ioeric, MaskRay, jkorous, mgrang, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D51422
llvm-svn: 341318
2018-09-03 22:37:43 +08:00
|
|
|
}
|
|
|
|
size_t SwapIndex::estimateMemoryUsage() const {
|
|
|
|
return snapshot()->estimateMemoryUsage();
|
|
|
|
}
|
|
|
|
|
[clangd] Introduce a "Symbol" class.
Summary:
* The "Symbol" class represents a C++ symbol in the codebase, containing all the
information of a C++ symbol needed by clangd. clangd will use it in clangd's
AST/dynamic index and global/static index (code completion and code
navigation).
* The SymbolCollector (another IndexAction) will be used to recollect the
symbols when the source file is changed (for ASTIndex), or to generate
all C++ symbols for the whole project.
In the long term (when index-while-building is ready), clangd should share a
same "Symbol" structure and IndexAction with index-while-building, but
for now we want to have some stuff working in clangd.
Reviewers: ioeric, sammccall, ilya-biryukov, malaperle
Reviewed By: sammccall
Subscribers: malaperle, klimek, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D40897
llvm-svn: 320486
2017-12-12 23:42:10 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|