2019-09-04 15:35:00 +08:00
|
|
|
//===--- Preamble.h - Reusing expensive parts of the AST ---------*- C++-*-===//
|
|
|
|
//
|
|
|
|
// 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
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// The vast majority of code in a typical translation unit is in the headers
|
|
|
|
// included at the top of the file.
|
|
|
|
//
|
|
|
|
// The preamble optimization says that we can parse this code once, and reuse
|
|
|
|
// the result multiple times. The preamble is invalidated by changes to the
|
|
|
|
// code in the preamble region, to the compile command, or to files on disk.
|
|
|
|
//
|
|
|
|
// This is the most important optimization in clangd: it allows operations like
|
|
|
|
// code-completion to have sub-second latency. It is supported by the
|
|
|
|
// PrecompiledPreamble functionality in clang, which wraps the techniques used
|
|
|
|
// by PCH files, modules etc into a convenient interface.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
|
|
|
|
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
|
|
|
|
|
2019-09-24 19:14:06 +08:00
|
|
|
#include "CollectMacros.h"
|
2019-09-04 15:35:00 +08:00
|
|
|
#include "Compiler.h"
|
|
|
|
#include "Diagnostics.h"
|
|
|
|
#include "FS.h"
|
|
|
|
#include "Headers.h"
|
2020-03-16 04:43:00 +08:00
|
|
|
#include "Path.h"
|
2019-09-04 15:35:00 +08:00
|
|
|
#include "index/CanonicalIncludes.h"
|
2020-03-16 04:43:00 +08:00
|
|
|
#include "clang/Frontend/CompilerInvocation.h"
|
2019-09-04 15:35:00 +08:00
|
|
|
#include "clang/Frontend/PrecompiledPreamble.h"
|
|
|
|
#include "clang/Tooling/CompilationDatabase.h"
|
|
|
|
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
namespace clangd {
|
|
|
|
|
|
|
|
/// The parsed preamble and associated data.
|
|
|
|
///
|
|
|
|
/// As we must avoid re-parsing the preamble, any information that can only
|
|
|
|
/// be obtained during parsing must be eagerly captured and stored here.
|
|
|
|
struct PreambleData {
|
2020-03-11 23:34:01 +08:00
|
|
|
PreambleData(const ParseInputs &Inputs, PrecompiledPreamble Preamble,
|
[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
|
|
|
std::vector<Diag> Diags, IncludeStructure Includes,
|
|
|
|
MainFileMacros Macros,
|
2019-09-04 15:35:00 +08:00
|
|
|
std::unique_ptr<PreambleFileStatusCache> StatCache,
|
|
|
|
CanonicalIncludes CanonIncludes);
|
|
|
|
|
[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
|
|
|
// Version of the ParseInputs this preamble was built from.
|
|
|
|
std::string Version;
|
2019-09-04 15:35:00 +08:00
|
|
|
tooling::CompileCommand CompileCommand;
|
|
|
|
PrecompiledPreamble Preamble;
|
|
|
|
std::vector<Diag> Diags;
|
|
|
|
// Processes like code completions and go-to-definitions will need #include
|
|
|
|
// information, and their compile action skips preamble range.
|
|
|
|
IncludeStructure Includes;
|
|
|
|
// Macros defined in the preamble section of the main file.
|
|
|
|
// Users care about headers vs main-file, not preamble vs non-preamble.
|
|
|
|
// These should be treated as main-file entities e.g. for code completion.
|
2019-09-24 19:14:06 +08:00
|
|
|
MainFileMacros Macros;
|
2019-09-04 15:35:00 +08:00
|
|
|
// Cache of FS operations performed when building the preamble.
|
|
|
|
// When reusing a preamble, this cache can be consumed to save IO.
|
|
|
|
std::unique_ptr<PreambleFileStatusCache> StatCache;
|
|
|
|
CanonicalIncludes CanonIncludes;
|
|
|
|
};
|
|
|
|
|
|
|
|
using PreambleParsedCallback =
|
|
|
|
std::function<void(ASTContext &, std::shared_ptr<clang::Preprocessor>,
|
|
|
|
const CanonicalIncludes &)>;
|
|
|
|
|
|
|
|
/// Build a preamble for the new inputs unless an old one can be reused.
|
|
|
|
/// If \p PreambleCallback is set, it will be run on top of the AST while
|
2020-03-16 04:43:00 +08:00
|
|
|
/// building the preamble.
|
2019-09-04 15:35:00 +08:00
|
|
|
std::shared_ptr<const PreambleData>
|
2020-03-13 18:52:19 +08:00
|
|
|
buildPreamble(PathRef FileName, CompilerInvocation CI,
|
2019-09-04 15:35:00 +08:00
|
|
|
const ParseInputs &Inputs, bool StoreInMemory,
|
|
|
|
PreambleParsedCallback PreambleCallback);
|
|
|
|
|
2020-03-16 04:43:00 +08:00
|
|
|
/// Returns true if \p Preamble is reusable for \p Inputs. Note that it will
|
|
|
|
/// return true when some missing headers are now available.
|
|
|
|
/// FIXME: Should return more information about the delta between \p Preamble
|
|
|
|
/// and \p Inputs, e.g. new headers.
|
|
|
|
bool isPreambleCompatible(const PreambleData &Preamble,
|
|
|
|
const ParseInputs &Inputs, PathRef FileName,
|
|
|
|
const CompilerInvocation &CI);
|
2019-09-04 15:35:00 +08:00
|
|
|
} // namespace clangd
|
|
|
|
} // namespace clang
|
|
|
|
|
|
|
|
#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
|