2017-05-16 17:38:59 +08:00
|
|
|
//===--- ClangdUnit.h -------------------------------------------*- C++-*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===---------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_CLANGDUNIT_H
|
|
|
|
|
2017-10-11 00:12:54 +08:00
|
|
|
#include "Function.h"
|
2017-05-16 17:38:59 +08:00
|
|
|
#include "Path.h"
|
2017-05-26 20:26:51 +08:00
|
|
|
#include "Protocol.h"
|
2017-09-30 00:41:23 +08:00
|
|
|
#include "clang/Frontend/FrontendAction.h"
|
2017-07-21 21:29:29 +08:00
|
|
|
#include "clang/Frontend/PrecompiledPreamble.h"
|
|
|
|
#include "clang/Serialization/ASTBitCodes.h"
|
|
|
|
#include "clang/Tooling/CompilationDatabase.h"
|
2017-05-16 17:38:59 +08:00
|
|
|
#include "clang/Tooling/Core/Replacement.h"
|
|
|
|
#include <memory>
|
2018-02-09 18:17:23 +08:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2017-05-16 17:38:59 +08:00
|
|
|
|
2017-05-23 21:42:59 +08:00
|
|
|
namespace llvm {
|
|
|
|
class raw_ostream;
|
|
|
|
}
|
|
|
|
|
2017-05-16 17:38:59 +08:00
|
|
|
namespace clang {
|
|
|
|
class PCHContainerOperations;
|
|
|
|
|
2017-05-26 20:26:51 +08:00
|
|
|
namespace vfs {
|
|
|
|
class FileSystem;
|
|
|
|
}
|
|
|
|
|
2017-05-16 17:38:59 +08:00
|
|
|
namespace tooling {
|
|
|
|
struct CompileCommand;
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace clangd {
|
|
|
|
|
|
|
|
/// A diagnostic with its FixIts.
|
|
|
|
struct DiagWithFixIts {
|
|
|
|
clangd::Diagnostic Diag;
|
[clangd] Emit ranges for clangd diagnostics, and fix off-by-one positions
Summary:
- when the diagnostic has an explicit range, we prefer that
- if the diagnostic has a fixit, its RemoveRange is our next choice
- otherwise we try to expand the diagnostic location into a whole token.
(inspired by VSCode, which does this client-side when given an empty range)
- if all else fails, we return the zero-width range as now.
(clients react in different ways to this, highlighting a token or a char)
- this includes the off-by-one fix from D40860, and borrows heavily from it
Reviewers: rwols, hokein
Subscribers: klimek, ilya-biryukov, cfe-commits
Differential Revision: https://reviews.llvm.org/D41118
llvm-svn: 320555
2017-12-13 16:48:42 +08:00
|
|
|
llvm::SmallVector<TextEdit, 1> FixIts;
|
2017-05-16 17:38:59 +08:00
|
|
|
};
|
|
|
|
|
2017-11-24 21:04:21 +08:00
|
|
|
// Stores Preamble and associated data.
|
|
|
|
struct PreambleData {
|
|
|
|
PreambleData(PrecompiledPreamble Preamble,
|
|
|
|
std::vector<serialization::DeclID> TopLevelDeclIDs,
|
|
|
|
std::vector<DiagWithFixIts> Diags);
|
|
|
|
|
|
|
|
PrecompiledPreamble Preamble;
|
|
|
|
std::vector<serialization::DeclID> TopLevelDeclIDs;
|
|
|
|
std::vector<DiagWithFixIts> Diags;
|
|
|
|
};
|
|
|
|
|
2018-01-23 23:07:52 +08:00
|
|
|
/// Information required to run clang, e.g. to parse AST or do code completion.
|
|
|
|
struct ParseInputs {
|
|
|
|
tooling::CompileCommand CompileCommand;
|
|
|
|
IntrusiveRefCntPtr<vfs::FileSystem> FS;
|
|
|
|
std::string Contents;
|
|
|
|
};
|
|
|
|
|
2017-08-01 23:51:38 +08:00
|
|
|
/// Stores and provides access to parsed AST.
|
|
|
|
class ParsedAST {
|
2017-05-16 17:38:59 +08:00
|
|
|
public:
|
2017-08-01 23:51:38 +08:00
|
|
|
/// Attempts to run Clang and store parsed AST. If \p Preamble is non-null
|
|
|
|
/// it is reused during parsing.
|
|
|
|
static llvm::Optional<ParsedAST>
|
[clangd] Pass Context implicitly using TLS.
Summary:
Instead of passing Context explicitly around, we now have a thread-local
Context object `Context::current()` which is an implicit argument to
every function.
Most manipulation of this should use the WithContextValue helper, which
augments the current Context to add a single KV pair, and restores the
old context on destruction.
Advantages are:
- less boilerplate in functions that just propagate contexts
- reading most code doesn't require understanding context at all, and
using context as values in fewer places still
- fewer options to pass the "wrong" context when it changes within a
scope (e.g. when using Span)
- contexts pass through interfaces we can't modify, such as VFS
- propagating contexts across threads was slightly tricky (e.g.
copy vs move, no move-init in lambdas), and is now encapsulated in
the threadpool
Disadvantages are all the usual TLS stuff - hidden magic, and
potential for higher memory usage on threads that don't use the
context. (In practice, it's just one pointer)
Reviewers: ilya-biryukov
Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D42517
llvm-svn: 323872
2018-01-31 21:40:48 +08:00
|
|
|
Build(std::unique_ptr<clang::CompilerInvocation> CI,
|
2017-11-24 21:04:21 +08:00
|
|
|
std::shared_ptr<const PreambleData> Preamble,
|
2017-08-01 23:51:38 +08:00
|
|
|
std::unique_ptr<llvm::MemoryBuffer> Buffer,
|
|
|
|
std::shared_ptr<PCHContainerOperations> PCHs,
|
2017-12-13 20:51:22 +08:00
|
|
|
IntrusiveRefCntPtr<vfs::FileSystem> VFS);
|
2017-08-01 23:51:38 +08:00
|
|
|
|
|
|
|
ParsedAST(ParsedAST &&Other);
|
|
|
|
ParsedAST &operator=(ParsedAST &&Other);
|
|
|
|
|
|
|
|
~ParsedAST();
|
|
|
|
|
|
|
|
ASTContext &getASTContext();
|
|
|
|
const ASTContext &getASTContext() const;
|
|
|
|
|
|
|
|
Preprocessor &getPreprocessor();
|
2018-01-10 01:32:00 +08:00
|
|
|
std::shared_ptr<Preprocessor> getPreprocessorPtr();
|
2017-08-01 23:51:38 +08:00
|
|
|
const Preprocessor &getPreprocessor() const;
|
|
|
|
|
|
|
|
/// This function returns all top-level decls, including those that come
|
|
|
|
/// from Preamble. Decls, coming from Preamble, have to be deserialized, so
|
|
|
|
/// this call might be expensive.
|
|
|
|
ArrayRef<const Decl *> getTopLevelDecls();
|
|
|
|
|
|
|
|
const std::vector<DiagWithFixIts> &getDiagnostics() const;
|
2017-05-23 21:42:59 +08:00
|
|
|
|
2018-01-25 22:32:21 +08:00
|
|
|
/// Returns the esitmated size of the AST and the accessory structures, in
|
|
|
|
/// bytes. Does not include the size of the preamble.
|
|
|
|
std::size_t getUsedBytes() const;
|
|
|
|
|
2017-05-16 17:38:59 +08:00
|
|
|
private:
|
2017-11-24 21:04:21 +08:00
|
|
|
ParsedAST(std::shared_ptr<const PreambleData> Preamble,
|
|
|
|
std::unique_ptr<CompilerInstance> Clang,
|
2017-08-01 23:51:38 +08:00
|
|
|
std::unique_ptr<FrontendAction> Action,
|
|
|
|
std::vector<const Decl *> TopLevelDecls,
|
|
|
|
std::vector<DiagWithFixIts> Diags);
|
2017-07-21 21:29:29 +08:00
|
|
|
|
2017-08-01 23:51:38 +08:00
|
|
|
private:
|
|
|
|
void ensurePreambleDeclsDeserialized();
|
|
|
|
|
2017-11-24 21:04:21 +08:00
|
|
|
// In-memory preambles must outlive the AST, it is important that this member
|
|
|
|
// goes before Clang and Action.
|
|
|
|
std::shared_ptr<const PreambleData> Preamble;
|
2017-08-01 23:51:38 +08:00
|
|
|
// We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called
|
|
|
|
// on it) and CompilerInstance used to run it. That way we don't have to do
|
|
|
|
// complex memory management of all Clang structures on our own. (They are
|
|
|
|
// stored in CompilerInstance and cleaned up by
|
|
|
|
// FrontendAction.EndSourceFile).
|
|
|
|
std::unique_ptr<CompilerInstance> Clang;
|
|
|
|
std::unique_ptr<FrontendAction> Action;
|
|
|
|
|
|
|
|
// Data, stored after parsing.
|
|
|
|
std::vector<DiagWithFixIts> Diags;
|
|
|
|
std::vector<const Decl *> TopLevelDecls;
|
2017-11-24 21:04:21 +08:00
|
|
|
bool PreambleDeclsDeserialized;
|
2017-08-01 23:51:38 +08:00
|
|
|
};
|
2017-07-21 21:29:29 +08:00
|
|
|
|
[clangd] Pass Context implicitly using TLS.
Summary:
Instead of passing Context explicitly around, we now have a thread-local
Context object `Context::current()` which is an implicit argument to
every function.
Most manipulation of this should use the WithContextValue helper, which
augments the current Context to add a single KV pair, and restores the
old context on destruction.
Advantages are:
- less boilerplate in functions that just propagate contexts
- reading most code doesn't require understanding context at all, and
using context as values in fewer places still
- fewer options to pass the "wrong" context when it changes within a
scope (e.g. when using Span)
- contexts pass through interfaces we can't modify, such as VFS
- propagating contexts across threads was slightly tricky (e.g.
copy vs move, no move-init in lambdas), and is now encapsulated in
the threadpool
Disadvantages are all the usual TLS stuff - hidden magic, and
potential for higher memory usage on threads that don't use the
context. (In practice, it's just one pointer)
Reviewers: ilya-biryukov
Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D42517
llvm-svn: 323872
2018-01-31 21:40:48 +08:00
|
|
|
using ASTParsedCallback = std::function<void(PathRef Path, ParsedAST *)>;
|
2017-12-20 02:00:37 +08:00
|
|
|
|
2017-08-01 23:51:38 +08:00
|
|
|
/// Manages resources, required by clangd. Allows to rebuild file with new
|
|
|
|
/// contents, and provides AST and Preamble for it.
|
2018-02-09 18:17:23 +08:00
|
|
|
class CppFile {
|
2017-08-01 23:51:38 +08:00
|
|
|
public:
|
2018-01-23 23:07:52 +08:00
|
|
|
CppFile(PathRef FileName, bool StorePreamblesInMemory,
|
2017-12-20 02:00:37 +08:00
|
|
|
std::shared_ptr<PCHContainerOperations> PCHs,
|
|
|
|
ASTParsedCallback ASTCallback);
|
2017-07-21 21:29:29 +08:00
|
|
|
|
2018-02-09 18:17:23 +08:00
|
|
|
/// Rebuild the AST and the preamble.
|
|
|
|
/// Returns a list of diagnostics or llvm::None, if an error occured.
|
[clangd] Pass Context implicitly using TLS.
Summary:
Instead of passing Context explicitly around, we now have a thread-local
Context object `Context::current()` which is an implicit argument to
every function.
Most manipulation of this should use the WithContextValue helper, which
augments the current Context to add a single KV pair, and restores the
old context on destruction.
Advantages are:
- less boilerplate in functions that just propagate contexts
- reading most code doesn't require understanding context at all, and
using context as values in fewer places still
- fewer options to pass the "wrong" context when it changes within a
scope (e.g. when using Span)
- contexts pass through interfaces we can't modify, such as VFS
- propagating contexts across threads was slightly tricky (e.g.
copy vs move, no move-init in lambdas), and is now encapsulated in
the threadpool
Disadvantages are all the usual TLS stuff - hidden magic, and
potential for higher memory usage on threads that don't use the
context. (In practice, it's just one pointer)
Reviewers: ilya-biryukov
Subscribers: klimek, jkorous-apple, ioeric, cfe-commits
Differential Revision: https://reviews.llvm.org/D42517
llvm-svn: 323872
2018-01-31 21:40:48 +08:00
|
|
|
llvm::Optional<std::vector<DiagWithFixIts>> rebuild(ParseInputs &&Inputs);
|
2018-02-09 18:17:23 +08:00
|
|
|
/// Returns the last built preamble.
|
|
|
|
const std::shared_ptr<const PreambleData> &getPreamble() const;
|
|
|
|
/// Returns the last built AST.
|
|
|
|
ParsedAST *getAST() const;
|
2018-01-25 22:32:21 +08:00
|
|
|
/// Returns an estimated size, in bytes, currently occupied by the AST and the
|
|
|
|
/// Preamble.
|
|
|
|
std::size_t getUsedBytes() const;
|
|
|
|
|
2017-08-01 23:51:38 +08:00
|
|
|
private:
|
2018-02-09 18:17:23 +08:00
|
|
|
/// Build a new preamble for \p Inputs. If the current preamble can be reused,
|
|
|
|
/// it is returned instead.
|
|
|
|
/// This method is const to ensure we don't incidentally modify any fields.
|
|
|
|
std::shared_ptr<const PreambleData>
|
|
|
|
rebuildPreamble(CompilerInvocation &CI,
|
2018-02-20 02:18:49 +08:00
|
|
|
const tooling::CompileCommand &Command,
|
2018-02-09 18:17:23 +08:00
|
|
|
IntrusiveRefCntPtr<vfs::FileSystem> FS,
|
|
|
|
llvm::MemoryBuffer &ContentsBuffer) const;
|
2017-07-21 21:29:29 +08:00
|
|
|
|
2018-02-19 19:15:33 +08:00
|
|
|
const Path FileName;
|
|
|
|
const bool StorePreamblesInMemory;
|
2017-06-29 00:12:10 +08:00
|
|
|
|
2018-02-20 02:18:49 +08:00
|
|
|
/// The last CompileCommand used to build AST and Preamble.
|
|
|
|
tooling::CompileCommand Command;
|
2018-02-09 18:17:23 +08:00
|
|
|
/// The last parsed AST.
|
|
|
|
llvm::Optional<ParsedAST> AST;
|
|
|
|
/// The last built Preamble.
|
|
|
|
std::shared_ptr<const PreambleData> Preamble;
|
|
|
|
/// Utility class required by clang
|
2017-07-21 21:29:29 +08:00
|
|
|
std::shared_ptr<PCHContainerOperations> PCHs;
|
2017-12-20 02:00:37 +08:00
|
|
|
/// This is called after the file is parsed. This can be nullptr if there is
|
|
|
|
/// no callback.
|
|
|
|
ASTParsedCallback ASTCallback;
|
2017-05-16 17:38:59 +08:00
|
|
|
};
|
|
|
|
|
2017-11-09 19:30:04 +08:00
|
|
|
/// Get the beginning SourceLocation at a specified \p Pos.
|
|
|
|
SourceLocation getBeginningOfIdentifier(ParsedAST &Unit, const Position &Pos,
|
|
|
|
const FileEntry *FE);
|
|
|
|
|
2017-08-01 23:51:38 +08:00
|
|
|
/// For testing/debugging purposes. Note that this method deserializes all
|
|
|
|
/// unserialized Decls, so use with care.
|
|
|
|
void dumpAST(ParsedAST &AST, llvm::raw_ostream &OS);
|
|
|
|
|
2017-05-16 17:38:59 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|
|
|
|
#endif
|