mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 20:40:11 +01:00
Stop using the clang tooling library to build an ASTUnit; that library is set up to process clang frontend arguments, assuming that something has already built frontend arguments from the compiler arguments. It is also too encapsulated and doesn't let us inspect and modify the compiler invocation before it's executed. Instead, build the AST unit directly in two phases: * FIrst, take a list of clang driver arguments and convert them into a list of compiler arguments, using `clang::createInvocation`. Internally, this uses the clang driver to build a frontend invocation, including building system-specific include paths as needed. * Then, directly build an ASTUnit from this compiler invocation. I've factored this so that we can split out the `createInvocation` step, with the intention that we may want to move it out of check and into the carbon driver with the rest of the driver-level argument handling, and we may want to customize some of the clang options before we invoke the clang frontend with that set of options. In order to make the invocation reusable, it no longer depends on the name of the carbon file importing the C++ code. In place of synthesizing a header file name as `<foo.carbon>.generated.cpp_imports.h`, we now insert line marker directives into the generated header so that errors in that header cause Clang to point a diagnostic back at the Carbon source file itself. This results in a minor improvement in the diagnostic output: we no longer refer to a nonexistent generated file. But the snippet still contains text that doesn't match the source code, so it remains imperfect. --------- Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
102 lines
3.4 KiB
C++
102 lines
3.4 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_LANGUAGE_SERVER_CONTEXT_H_
|
|
#define CARBON_TOOLCHAIN_LANGUAGE_SERVER_CONTEXT_H_
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
#include "clang-tools-extra/clangd/LSPBinder.h"
|
|
#include "common/map.h"
|
|
#include "toolchain/base/shared_value_stores.h"
|
|
#include "toolchain/diagnostics/diagnostic_consumer.h"
|
|
#include "toolchain/diagnostics/diagnostic_emitter.h"
|
|
#include "toolchain/diagnostics/file_diagnostics.h"
|
|
#include "toolchain/install/install_paths.h"
|
|
#include "toolchain/lex/tokenized_buffer.h"
|
|
#include "toolchain/parse/tree_and_subtrees.h"
|
|
#include "toolchain/sem_ir/file.h"
|
|
#include "toolchain/source/source_buffer.h"
|
|
|
|
namespace Carbon::LanguageServer {
|
|
|
|
// Context for LSP call handling.
|
|
class Context {
|
|
public:
|
|
// Cached information for an open file.
|
|
class File {
|
|
public:
|
|
explicit File(clang::clangd::URIForFile uri) : uri_(std::move(uri)) {}
|
|
|
|
// Changes the file's text, updating dependent state.
|
|
auto SetText(Context& context, std::optional<int64_t> version,
|
|
llvm::StringRef text) -> void;
|
|
|
|
auto text() const -> llvm::StringRef { return source_->text(); }
|
|
|
|
auto tree_and_subtrees() const -> const Parse::TreeAndSubtrees& {
|
|
return *tree_and_subtrees_;
|
|
}
|
|
|
|
private:
|
|
// The filename, stable across instances.
|
|
clang::clangd::URIForFile uri_;
|
|
|
|
// Current file content, and derived values.
|
|
std::unique_ptr<SourceBuffer> source_;
|
|
std::unique_ptr<SharedValueStores> value_stores_;
|
|
std::unique_ptr<Lex::TokenizedBuffer> tokens_;
|
|
std::unique_ptr<Parse::Tree> tree_;
|
|
std::unique_ptr<Parse::TreeAndSubtrees> tree_and_subtrees_;
|
|
};
|
|
|
|
// `vlog_stream` is optional; other parameters are required.
|
|
explicit Context(const InstallPaths* installation,
|
|
llvm::raw_ostream* vlog_stream,
|
|
Diagnostics::Consumer* consumer,
|
|
clang::clangd::LSPBinder::RawOutgoing* outgoing)
|
|
: installation_(installation),
|
|
vlog_stream_(vlog_stream),
|
|
file_emitter_(consumer),
|
|
no_loc_emitter_(consumer),
|
|
outgoing_(outgoing) {}
|
|
|
|
// Returns a reference to the file if it's known, or diagnoses and returns
|
|
// null.
|
|
auto LookupFile(llvm::StringRef filename) -> File*;
|
|
|
|
// Wrapper for LSP notification.
|
|
auto PublishDiagnostics(clang::clangd::PublishDiagnosticsParams params)
|
|
-> void {
|
|
outgoing_->notify("textDocument/publishDiagnostics", params);
|
|
}
|
|
|
|
auto installation() -> const InstallPaths& { return *installation_; }
|
|
|
|
auto vlog_stream() -> llvm::raw_ostream* { return vlog_stream_; }
|
|
auto file_emitter() -> Diagnostics::FileEmitter& { return file_emitter_; }
|
|
auto no_loc_emitter() -> Diagnostics::NoLocEmitter& {
|
|
return no_loc_emitter_;
|
|
}
|
|
|
|
auto files() -> Map<std::string, File>& { return files_; }
|
|
|
|
private:
|
|
const InstallPaths* installation_;
|
|
|
|
// Diagnostic and output streams.
|
|
llvm::raw_ostream* vlog_stream_;
|
|
Diagnostics::FileEmitter file_emitter_;
|
|
Diagnostics::NoLocEmitter no_loc_emitter_;
|
|
clang::clangd::LSPBinder::RawOutgoing* outgoing_;
|
|
|
|
// Content of files managed by the language client.
|
|
Map<std::string, File> files_;
|
|
};
|
|
|
|
} // namespace Carbon::LanguageServer
|
|
|
|
#endif // CARBON_TOOLCHAIN_LANGUAGE_SERVER_CONTEXT_H_
|