2017-12-15 20:25:02 +08:00
|
|
|
//===--- FileIndex.h - Index for files. ---------------------------- C++-*-===//
|
2017-12-14 22:50:58 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2017-12-14 22:50:58 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2017-12-15 20:25:02 +08:00
|
|
|
//
|
|
|
|
// FileIndex implements SymbolIndex for symbols from a set of files. Symbols are
|
2019-12-16 17:33:56 +08:00
|
|
|
// maintained at source-file granularity (e.g. with ASTs), and files can be
|
2017-12-15 20:25:02 +08:00
|
|
|
// updated dynamically.
|
|
|
|
//
|
2018-08-15 00:03:32 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2017-12-14 22:50:58 +08:00
|
|
|
|
2017-12-15 20:25:02 +08:00
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
|
2017-12-14 22:50:58 +08:00
|
|
|
|
2020-04-08 22:14:53 +08:00
|
|
|
#include "Headers.h"
|
2017-12-14 22:50:58 +08:00
|
|
|
#include "Index.h"
|
2017-12-15 20:25:02 +08:00
|
|
|
#include "MemIndex.h"
|
2018-10-04 22:20:22 +08:00
|
|
|
#include "Merge.h"
|
2019-02-05 00:19:57 +08:00
|
|
|
#include "index/CanonicalIncludes.h"
|
2020-04-08 22:14:53 +08:00
|
|
|
#include "index/Ref.h"
|
|
|
|
#include "index/Relation.h"
|
|
|
|
#include "index/Serialization.h"
|
2019-02-28 21:23:03 +08:00
|
|
|
#include "index/Symbol.h"
|
[clangd] Move non-clang base pieces into separate support/ lib. NFCI
Summary:
This enforces layering, reduces a sprawling clangd/ directory, and makes life
easier for embedders.
Reviewers: kbobyrev
Subscribers: mgorny, ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, jfb, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D79014
2020-04-28 23:49:17 +08:00
|
|
|
#include "support/Path.h"
|
2018-05-24 23:50:15 +08:00
|
|
|
#include "clang/Lex/Preprocessor.h"
|
2020-04-08 22:14:53 +08:00
|
|
|
#include "clang/Tooling/CompilationDatabase.h"
|
|
|
|
#include "llvm/ADT/DenseSet.h"
|
|
|
|
#include "llvm/ADT/Optional.h"
|
|
|
|
#include "llvm/ADT/StringMap.h"
|
|
|
|
#include "llvm/ADT/StringRef.h"
|
2018-09-18 18:30:44 +08:00
|
|
|
#include <memory>
|
2020-04-08 22:14:53 +08:00
|
|
|
#include <vector>
|
2017-12-14 22:50:58 +08:00
|
|
|
|
|
|
|
namespace clang {
|
2019-11-16 08:36:00 +08:00
|
|
|
class ASTContext;
|
2017-12-14 22:50:58 +08:00
|
|
|
namespace clangd {
|
2019-09-03 23:34:47 +08:00
|
|
|
class ParsedAST;
|
2017-12-14 22:50:58 +08:00
|
|
|
|
2018-10-16 16:53:52 +08:00
|
|
|
/// Select between in-memory index implementations, which have tradeoffs.
|
|
|
|
enum class IndexType {
|
|
|
|
// MemIndex is trivially cheap to build, but has poor query performance.
|
|
|
|
Light,
|
|
|
|
// Dex is relatively expensive to build and uses more memory, but is fast.
|
|
|
|
Heavy,
|
|
|
|
};
|
|
|
|
|
2018-11-06 18:55:21 +08:00
|
|
|
/// How to handle duplicated symbols across multiple files.
|
|
|
|
enum class DuplicateHandling {
|
|
|
|
// Pick a random symbol. Less accurate but faster.
|
|
|
|
PickOne,
|
|
|
|
// Merge symbols. More accurate but slower.
|
|
|
|
Merge,
|
|
|
|
};
|
|
|
|
|
2020-04-29 17:21:14 +08:00
|
|
|
/// A container of slabs associated with a key. It can be updated at key
|
|
|
|
/// granularity, replacing all slabs belonging to a key with a new set. Keys are
|
|
|
|
/// usually file paths/uris.
|
2017-12-14 22:50:58 +08:00
|
|
|
///
|
2020-04-29 17:21:14 +08:00
|
|
|
/// This implements snapshot semantics. Each update will create a new snapshot
|
|
|
|
/// for all slabs of the Key. Snapshots are managed with shared pointers that
|
|
|
|
/// are shared between this class and the users. For each key, this class only
|
|
|
|
/// stores a pointer pointing to the newest snapshot, and an outdated snapshot
|
|
|
|
/// is deleted by the last owner of the snapshot, either this class or the
|
|
|
|
/// symbol index.
|
2017-12-14 22:50:58 +08:00
|
|
|
///
|
|
|
|
/// The snapshot semantics keeps critical sections minimal since we only need
|
2018-09-01 15:47:03 +08:00
|
|
|
/// locking when we swap or obtain references to snapshots.
|
2017-12-14 22:50:58 +08:00
|
|
|
class FileSymbols {
|
|
|
|
public:
|
2020-04-29 17:21:14 +08:00
|
|
|
/// Updates all slabs associated with the \p Key.
|
|
|
|
/// If either is nullptr, corresponding data for \p Key will be removed.
|
|
|
|
/// If CountReferences is true, \p Refs will be used for counting references
|
2019-05-09 22:22:07 +08:00
|
|
|
/// during merging.
|
2020-04-29 17:21:14 +08:00
|
|
|
void update(llvm::StringRef Key, std::unique_ptr<SymbolSlab> Symbols,
|
2019-06-15 10:26:47 +08:00
|
|
|
std::unique_ptr<RefSlab> Refs,
|
|
|
|
std::unique_ptr<RelationSlab> Relations, bool CountReferences);
|
2017-12-14 22:50:58 +08:00
|
|
|
|
2020-04-29 17:21:14 +08:00
|
|
|
/// The index keeps the slabs alive.
|
2019-05-09 22:22:07 +08:00
|
|
|
/// Will count Symbol::References based on number of references in the main
|
|
|
|
/// files, while building the index with DuplicateHandling::Merge option.
|
2018-10-16 16:53:52 +08:00
|
|
|
std::unique_ptr<SymbolIndex>
|
2018-11-06 18:55:21 +08:00
|
|
|
buildIndex(IndexType,
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
DuplicateHandling DuplicateHandle = DuplicateHandling::PickOne);
|
2018-09-01 03:53:37 +08:00
|
|
|
|
2017-12-14 22:50:58 +08:00
|
|
|
private:
|
2019-05-09 22:22:07 +08:00
|
|
|
struct RefSlabAndCountReferences {
|
|
|
|
std::shared_ptr<RefSlab> Slab;
|
|
|
|
bool CountReferences = false;
|
|
|
|
};
|
2017-12-14 22:50:58 +08:00
|
|
|
mutable std::mutex Mutex;
|
|
|
|
|
2020-04-29 17:21:14 +08:00
|
|
|
llvm::StringMap<std::shared_ptr<SymbolSlab>> SymbolsSnapshot;
|
|
|
|
llvm::StringMap<RefSlabAndCountReferences> RefsSnapshot;
|
|
|
|
llvm::StringMap<std::shared_ptr<RelationSlab>> RelatiosSnapshot;
|
2017-12-14 22:50:58 +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
|
|
|
/// This manages symbols from files and an in-memory index on all symbols.
|
2018-09-18 18:30:44 +08:00
|
|
|
/// FIXME: Expose an interface to remove files that are closed.
|
2018-10-04 22:20:22 +08:00
|
|
|
class FileIndex : public MergedIndex {
|
2017-12-15 20:25:02 +08:00
|
|
|
public:
|
[clangd] Cleanup: stop passing around list of supported URI schemes.
Summary:
Instead of passing around a list of supported URI schemes in clangd, we
expose an interface to convert a path to URI using any compatible scheme
that has been registered. It favors customized schemes and falls
back to "file" when no other scheme works.
Changes in this patch are:
- URI::create(AbsPath, URISchemes) -> URI::create(AbsPath). The new API finds a
compatible scheme from the registry.
- Remove URISchemes option everywhere (ClangdServer, SymbolCollecter, FileIndex etc).
- Unit tests will use "unittest" by default.
- Move "test" scheme from ClangdLSPServer to ClangdMain.cpp, and only
register the test scheme when lit-test or enable-lit-scheme is set.
(The new flag is added to make lit protocol.test work; I wonder if there
is alternative here.)
Reviewers: sammccall
Reviewed By: sammccall
Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, cfe-commits
Differential Revision: https://reviews.llvm.org/D54800
llvm-svn: 347467
2018-11-22 23:02:05 +08:00
|
|
|
FileIndex(bool UseDex = true);
|
2018-06-15 16:55:00 +08:00
|
|
|
|
2018-09-18 18:30:44 +08:00
|
|
|
/// Update preamble symbols of file \p Path with all declarations in \p AST
|
|
|
|
/// and macros in \p PP.
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
void updatePreamble(PathRef Path, llvm::StringRef Version, ASTContext &AST,
|
2019-02-05 00:19:57 +08:00
|
|
|
std::shared_ptr<Preprocessor> PP,
|
|
|
|
const CanonicalIncludes &Includes);
|
2018-09-18 18:30:44 +08:00
|
|
|
|
2018-09-18 21:35:16 +08:00
|
|
|
/// Update symbols and references from main file \p Path with
|
|
|
|
/// `indexMainDecls`.
|
|
|
|
void updateMain(PathRef Path, ParsedAST &AST);
|
[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
|
|
|
|
2018-09-18 18:30:44 +08:00
|
|
|
private:
|
2018-10-16 16:53:52 +08:00
|
|
|
bool UseDex; // FIXME: this should be always on.
|
2018-09-18 18:30:44 +08:00
|
|
|
|
2020-04-08 22:14:53 +08:00
|
|
|
// Contains information from each file's preamble only. Symbols and relations
|
|
|
|
// are sharded per declaration file to deduplicate multiple symbols and reduce
|
|
|
|
// memory usage.
|
2018-09-18 18:30:44 +08:00
|
|
|
// Missing information:
|
|
|
|
// - symbol refs (these are always "from the main file")
|
|
|
|
// - definition locations in the main file
|
|
|
|
//
|
2020-04-08 22:14:53 +08:00
|
|
|
// Note that we store only one version of a header, hence symbols appearing in
|
|
|
|
// different PP states will be missing.
|
2018-09-18 18:30:44 +08:00
|
|
|
FileSymbols PreambleSymbols;
|
|
|
|
SwapIndex PreambleIndex;
|
|
|
|
|
|
|
|
// Contains information from each file's main AST.
|
|
|
|
// These are updated frequently (on file change), but are relatively small.
|
|
|
|
// Mostly contains:
|
|
|
|
// - refs to symbols declared in the preamble and referenced from main
|
|
|
|
// - symbols declared both in the main file and the preamble
|
|
|
|
// (Note that symbols *only* in the main file are not indexed).
|
|
|
|
FileSymbols MainFileSymbols;
|
|
|
|
SwapIndex MainFileIndex;
|
2017-12-15 20:25:02 +08:00
|
|
|
};
|
|
|
|
|
2019-06-15 10:26:47 +08:00
|
|
|
using SlabTuple = std::tuple<SymbolSlab, RefSlab, RelationSlab>;
|
|
|
|
|
2018-09-18 21:35:16 +08:00
|
|
|
/// Retrieves symbols and refs of local top level decls in \p AST (i.e.
|
|
|
|
/// `AST.getLocalTopLevelDecls()`).
|
2018-04-30 23:24:17 +08:00
|
|
|
/// Exposed to assist in unit tests.
|
2019-06-15 10:26:47 +08:00
|
|
|
SlabTuple indexMainDecls(ParsedAST &AST);
|
2018-09-18 18:30:44 +08:00
|
|
|
|
2019-12-12 19:12:17 +08:00
|
|
|
/// Index declarations from \p AST and macros from \p PP that are declared in
|
2018-09-18 18:30:44 +08:00
|
|
|
/// included headers.
|
[clangd] Track document versions, include them with diags, enhance logs
Summary:
This ties to an LSP feature (diagnostic versioning) but really a lot
of the value is in being able to log what's happening with file versions
and queues more descriptively and clearly.
As such it's fairly invasive, for a logging patch :-\
Key decisions:
- at the LSP layer, we don't reqire the client to provide versions (LSP
makes it mandatory but we never enforced it). If not provided,
versions start at 0 and increment. DraftStore handles this.
- don't propagate magically using contexts, but rather manually:
addDocument -> ParseInputs -> (ParsedAST, Preamble, various callbacks)
Context-propagation would hide the versions from ClangdServer, which
would make producing good log messages hard
- within ClangdServer, treat versions as opaque and unordered.
std::string is a convenient type for this, and allows richer versions
for embedders. They're "mandatory" but "null" is a reasonable default.
Subscribers: ilya-biryukov, javed.absar, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D75582
2020-03-04 07:33:29 +08:00
|
|
|
SlabTuple indexHeaderSymbols(llvm::StringRef Version, ASTContext &AST,
|
|
|
|
std::shared_ptr<Preprocessor> PP,
|
2019-06-15 10:26:47 +08:00
|
|
|
const CanonicalIncludes &Includes);
|
2018-04-30 23:24:17 +08:00
|
|
|
|
2020-04-08 22:14:53 +08:00
|
|
|
/// Takes slabs coming from a TU (multiple files) and shards them per
|
|
|
|
/// declaration location.
|
|
|
|
struct FileShardedIndex {
|
|
|
|
/// \p HintPath is used to convert file URIs stored in symbols into absolute
|
|
|
|
/// paths.
|
2020-04-29 17:21:14 +08:00
|
|
|
explicit FileShardedIndex(IndexFileIn Input);
|
2020-04-08 22:14:53 +08:00
|
|
|
|
2020-04-29 17:21:14 +08:00
|
|
|
/// Returns uris for all files that has a shard.
|
|
|
|
std::vector<llvm::StringRef> getAllSources() const;
|
2020-04-08 22:14:53 +08:00
|
|
|
|
2020-04-29 17:21:14 +08:00
|
|
|
/// Generates index shard for the \p Uri. Note that this function results in
|
2020-04-08 22:14:53 +08:00
|
|
|
/// a copy of all the relevant data.
|
|
|
|
/// Returned index will always have Symbol/Refs/Relation Slabs set, even if
|
|
|
|
/// they are empty.
|
2020-04-29 17:21:14 +08:00
|
|
|
llvm::Optional<IndexFileIn> getShard(llvm::StringRef Uri) const;
|
2020-04-08 22:14:53 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
// Contains all the information that belongs to a single file.
|
|
|
|
struct FileShard {
|
|
|
|
// Either declared or defined in the file.
|
|
|
|
llvm::DenseSet<const Symbol *> Symbols;
|
|
|
|
// Reference occurs in the file.
|
|
|
|
llvm::DenseSet<const Ref *> Refs;
|
|
|
|
// Subject is declared in the file.
|
|
|
|
llvm::DenseSet<const Relation *> Relations;
|
|
|
|
// Contains edges for only the direct includes.
|
|
|
|
IncludeGraph IG;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Keeps all the information alive.
|
|
|
|
const IndexFileIn Index;
|
2020-04-29 17:21:14 +08:00
|
|
|
// Mapping from URIs to slab information.
|
2020-04-08 22:14:53 +08:00
|
|
|
llvm::StringMap<FileShard> Shards;
|
|
|
|
// Used to build RefSlabs.
|
|
|
|
llvm::DenseMap<const Ref *, SymbolID> RefToSymID;
|
|
|
|
};
|
|
|
|
|
2017-12-14 22:50:58 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|
|
|
|
|
2017-12-15 20:25:02 +08:00
|
|
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_FILEINDEX_H
|