mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-06 08:54:47 +01:00
Use DiagnosticEmitter for phase-specific types (#5188)
Given the namespacing of `Diagnostics` in #5173, now we can use `DiagnosticEmitter` for phase-specific emitters. This is consistent with how we do `Context`, and also check had started this with `DiagnosticBuilder` in anticipation of the namespacing. Also renames `Emitter::DiagnosticBuilder` to `Emitter::Builder` for consistency with other `Diagnostics` entities. In check, I'm still splitting `DiagnosticEmitterBase` and `DiagnosticEmitter` just to keep the emitter definition separate from the context. Also cleans up some incorrect check diagnostic emitter dependencies in lower.
This commit is contained in:
@@ -160,10 +160,10 @@ cc_library(
|
||||
hdrs = ["check.h"],
|
||||
deps = [
|
||||
":context",
|
||||
":diagnostic_emitter",
|
||||
":dump",
|
||||
":impl",
|
||||
":pointer_dereference",
|
||||
":sem_ir_loc_diagnostic_emitter",
|
||||
"//common:check",
|
||||
"//common:error",
|
||||
"//common:map",
|
||||
@@ -287,9 +287,9 @@ cc_library(
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "sem_ir_loc_diagnostic_emitter",
|
||||
srcs = ["sem_ir_loc_diagnostic_emitter.cpp"],
|
||||
hdrs = ["sem_ir_loc_diagnostic_emitter.h"],
|
||||
name = "diagnostic_emitter",
|
||||
srcs = ["diagnostic_emitter.cpp"],
|
||||
hdrs = ["diagnostic_emitter.h"],
|
||||
deps = [
|
||||
":context",
|
||||
"//common:raw_string_ostream",
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#include "common/map.h"
|
||||
#include "toolchain/check/check_unit.h"
|
||||
#include "toolchain/check/context.h"
|
||||
#include "toolchain/check/diagnostic_emitter.h"
|
||||
#include "toolchain/check/diagnostic_helpers.h"
|
||||
#include "toolchain/check/sem_ir_loc_diagnostic_emitter.h"
|
||||
#include "toolchain/diagnostics/diagnostic.h"
|
||||
#include "toolchain/diagnostics/format_providers.h"
|
||||
#include "toolchain/lex/token_kind.h"
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#include "common/ostream.h"
|
||||
#include "toolchain/base/shared_value_stores.h"
|
||||
#include "toolchain/base/timings.h"
|
||||
#include "toolchain/check/sem_ir_loc_diagnostic_emitter.h"
|
||||
#include "toolchain/check/diagnostic_emitter.h"
|
||||
#include "toolchain/diagnostics/diagnostic_emitter.h"
|
||||
#include "toolchain/parse/tree_and_subtrees.h"
|
||||
#include "toolchain/sem_ir/file.h"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "toolchain/check/check.h"
|
||||
#include "toolchain/check/context.h"
|
||||
#include "toolchain/check/sem_ir_loc_diagnostic_emitter.h"
|
||||
#include "toolchain/check/diagnostic_emitter.h"
|
||||
#include "toolchain/parse/node_ids.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
|
||||
@@ -181,7 +181,7 @@ class CheckUnit {
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs_;
|
||||
llvm::raw_ostream* vlog_stream_;
|
||||
|
||||
SemIRLocDiagnosticEmitter emitter_;
|
||||
DiagnosticEmitter emitter_;
|
||||
Context context_;
|
||||
};
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
Context::Context(Diagnostics::Emitter<SemIRLoc>* emitter,
|
||||
Context::Context(DiagnosticEmitterBase* emitter,
|
||||
Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter,
|
||||
SemIR::File* sem_ir, int imported_ir_count, int total_ir_count,
|
||||
llvm::raw_ostream* vlog_stream)
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "toolchain/base/value_store.h"
|
||||
#include "toolchain/check/decl_introducer_state.h"
|
||||
#include "toolchain/check/decl_name_stack.h"
|
||||
#include "toolchain/check/diagnostic_helpers.h"
|
||||
#include "toolchain/check/full_pattern_stack.h"
|
||||
#include "toolchain/check/generic_region_stack.h"
|
||||
#include "toolchain/check/global_init.h"
|
||||
@@ -50,7 +51,7 @@ namespace Carbon::Check {
|
||||
class Context {
|
||||
public:
|
||||
// Stores references for work.
|
||||
explicit Context(Diagnostics::Emitter<SemIRLoc>* emitter,
|
||||
explicit Context(DiagnosticEmitterBase* emitter,
|
||||
Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter,
|
||||
SemIR::File* sem_ir, int imported_ir_count,
|
||||
int total_ir_count, llvm::raw_ostream* vlog_stream);
|
||||
@@ -69,7 +70,7 @@ class Context {
|
||||
return tokens().GetKind(parse_tree().node_token(node_id));
|
||||
}
|
||||
|
||||
auto emitter() -> Diagnostics::Emitter<SemIRLoc>& { return *emitter_; }
|
||||
auto emitter() -> DiagnosticEmitterBase& { return *emitter_; }
|
||||
|
||||
auto parse_tree_and_subtrees() -> const Parse::TreeAndSubtrees& {
|
||||
return tree_and_subtrees_getter_();
|
||||
@@ -276,7 +277,7 @@ class Context {
|
||||
|
||||
private:
|
||||
// Handles diagnostics.
|
||||
Diagnostics::Emitter<SemIRLoc>* emitter_;
|
||||
DiagnosticEmitterBase* emitter_;
|
||||
|
||||
// Returns a lazily constructed TreeAndSubtrees.
|
||||
Parse::GetTreeAndSubtreesFn tree_and_subtrees_getter_;
|
||||
|
||||
+10
-10
@@ -2,7 +2,7 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#include "toolchain/check/sem_ir_loc_diagnostic_emitter.h"
|
||||
#include "toolchain/check/diagnostic_emitter.h"
|
||||
|
||||
#include "common/raw_string_ostream.h"
|
||||
#include "toolchain/sem_ir/absolute_node_id.h"
|
||||
@@ -10,8 +10,7 @@
|
||||
|
||||
namespace Carbon::Check {
|
||||
|
||||
auto SemIRLocDiagnosticEmitter::ConvertLoc(SemIRLoc loc,
|
||||
ContextFnT context_fn) const
|
||||
auto DiagnosticEmitter::ConvertLoc(SemIRLoc loc, ContextFnT context_fn) const
|
||||
-> Diagnostics::ConvertedLoc {
|
||||
auto converted = ConvertLocImpl(loc, context_fn);
|
||||
|
||||
@@ -33,8 +32,8 @@ auto SemIRLocDiagnosticEmitter::ConvertLoc(SemIRLoc loc,
|
||||
return converted;
|
||||
}
|
||||
|
||||
auto SemIRLocDiagnosticEmitter::ConvertLocImpl(SemIRLoc loc,
|
||||
ContextFnT context_fn) const
|
||||
auto DiagnosticEmitter::ConvertLocImpl(SemIRLoc loc,
|
||||
ContextFnT context_fn) const
|
||||
-> Diagnostics::ConvertedLoc {
|
||||
llvm::SmallVector<SemIR::AbsoluteNodeId> absolute_node_ids =
|
||||
loc.is_inst_id_ ? SemIR::GetAbsoluteNodeId(sem_ir_, loc.inst_id_)
|
||||
@@ -57,16 +56,17 @@ auto SemIRLocDiagnosticEmitter::ConvertLocImpl(SemIRLoc loc,
|
||||
return ConvertLocInFile(final_node_id, loc.token_only_, context_fn);
|
||||
}
|
||||
|
||||
auto SemIRLocDiagnosticEmitter::ConvertLocInFile(
|
||||
SemIR::AbsoluteNodeId absolute_node_id, bool token_only,
|
||||
ContextFnT /*context_fn*/) const -> Diagnostics::ConvertedLoc {
|
||||
auto DiagnosticEmitter::ConvertLocInFile(SemIR::AbsoluteNodeId absolute_node_id,
|
||||
bool token_only,
|
||||
ContextFnT /*context_fn*/) const
|
||||
-> Diagnostics::ConvertedLoc {
|
||||
const auto& tree_and_subtrees =
|
||||
tree_and_subtrees_getters_[absolute_node_id.check_ir_id.index]();
|
||||
return tree_and_subtrees.NodeToDiagnosticLoc(absolute_node_id.node_id,
|
||||
token_only);
|
||||
}
|
||||
|
||||
auto SemIRLocDiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
|
||||
auto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
|
||||
if (auto* library_name_id = llvm::any_cast<SemIR::LibraryNameId>(&arg)) {
|
||||
std::string library_name;
|
||||
if (*library_name_id == SemIR::LibraryNameId::Default) {
|
||||
@@ -121,7 +121,7 @@ auto SemIRLocDiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any {
|
||||
return llvm::APSInt(typed_int->value,
|
||||
!sem_ir_->types().IsSignedInt(typed_int->type));
|
||||
}
|
||||
return Diagnostics::Emitter<SemIRLoc>::ConvertArg(arg);
|
||||
return DiagnosticEmitterBase::ConvertArg(arg);
|
||||
}
|
||||
|
||||
} // namespace Carbon::Check
|
||||
+6
-6
@@ -2,8 +2,8 @@
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
#ifndef CARBON_TOOLCHAIN_CHECK_SEM_IR_LOC_DIAGNOSTIC_EMITTER_H_
|
||||
#define CARBON_TOOLCHAIN_CHECK_SEM_IR_LOC_DIAGNOSTIC_EMITTER_H_
|
||||
#ifndef CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_EMITTER_H_
|
||||
#define CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_EMITTER_H_
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
#include "toolchain/check/diagnostic_helpers.h"
|
||||
@@ -17,13 +17,13 @@
|
||||
namespace Carbon::Check {
|
||||
|
||||
// Handles the transformation of a SemIRLoc to a DiagnosticLoc.
|
||||
class SemIRLocDiagnosticEmitter : public Diagnostics::Emitter<SemIRLoc> {
|
||||
class DiagnosticEmitter : public DiagnosticEmitterBase {
|
||||
public:
|
||||
explicit SemIRLocDiagnosticEmitter(
|
||||
explicit DiagnosticEmitter(
|
||||
Diagnostics::Consumer* consumer,
|
||||
llvm::ArrayRef<Parse::GetTreeAndSubtreesFn> tree_and_subtrees_getters,
|
||||
const SemIR::File* sem_ir)
|
||||
: Emitter(consumer),
|
||||
: DiagnosticEmitterBase(consumer),
|
||||
tree_and_subtrees_getters_(tree_and_subtrees_getters),
|
||||
sem_ir_(sem_ir) {}
|
||||
|
||||
@@ -69,4 +69,4 @@ class SemIRLocDiagnosticEmitter : public Diagnostics::Emitter<SemIRLoc> {
|
||||
|
||||
} // namespace Carbon::Check
|
||||
|
||||
#endif // CARBON_TOOLCHAIN_CHECK_SEM_IR_LOC_DIAGNOSTIC_EMITTER_H_
|
||||
#endif // CARBON_TOOLCHAIN_CHECK_DIAGNOSTIC_EMITTER_H_
|
||||
@@ -33,7 +33,7 @@ class SemIRLoc {
|
||||
|
||||
private:
|
||||
// Only allow member access for diagnostics.
|
||||
friend class SemIRLocDiagnosticEmitter;
|
||||
friend class DiagnosticEmitter;
|
||||
// And also for eval to unwrap a LocId for calling into the rest of Check.
|
||||
friend class UnwrapSemIRLoc;
|
||||
|
||||
@@ -46,7 +46,11 @@ class SemIRLoc {
|
||||
bool token_only_;
|
||||
};
|
||||
|
||||
using DiagnosticBuilder = Diagnostics::Emitter<SemIRLoc>::DiagnosticBuilder;
|
||||
// We define the emitter separately for dependencies, so only provide a base
|
||||
// here.
|
||||
using DiagnosticEmitterBase = Diagnostics::Emitter<SemIRLoc>;
|
||||
|
||||
using DiagnosticBuilder = DiagnosticEmitterBase::Builder;
|
||||
|
||||
// A function that forms a diagnostic for some kind of problem. The
|
||||
// DiagnosticBuilder is returned rather than emitted so that the caller
|
||||
|
||||
@@ -187,9 +187,7 @@ class EvalContext {
|
||||
|
||||
auto sem_ir() -> SemIR::File& { return context().sem_ir(); }
|
||||
|
||||
auto emitter() -> Diagnostics::Emitter<SemIRLoc>& {
|
||||
return context().emitter();
|
||||
}
|
||||
auto emitter() -> DiagnosticEmitterBase& { return context().emitter(); }
|
||||
|
||||
private:
|
||||
// The type-checking context in which we're performing evaluation.
|
||||
|
||||
@@ -14,7 +14,7 @@ static auto StartDiagnoseNotAllowed(
|
||||
Context& context,
|
||||
const Diagnostics::DiagnosticBase<TokenKinds...>& diagnostic_base,
|
||||
Parse::NodeId modifier_node, Lex::TokenKind declaration_kind)
|
||||
-> Diagnostics::Emitter<SemIRLoc>::DiagnosticBuilder {
|
||||
-> DiagnosticBuilder {
|
||||
if constexpr (sizeof...(TokenKinds) == 0) {
|
||||
return context.emitter().Build(modifier_node, diagnostic_base);
|
||||
} else if constexpr (sizeof...(TokenKinds) == 1) {
|
||||
|
||||
@@ -69,19 +69,18 @@ class Emitter {
|
||||
// expected usage.
|
||||
// This is nodiscard to protect against accidentally building a diagnostic
|
||||
// without emitting it.
|
||||
class [[nodiscard]] DiagnosticBuilder {
|
||||
class [[nodiscard]] Builder {
|
||||
public:
|
||||
// DiagnosticBuilder is move-only and cannot be copied.
|
||||
DiagnosticBuilder(DiagnosticBuilder&&) noexcept = default;
|
||||
auto operator=(DiagnosticBuilder&&) noexcept
|
||||
-> DiagnosticBuilder& = default;
|
||||
// Builder is move-only and cannot be copied.
|
||||
Builder(Builder&&) noexcept = default;
|
||||
auto operator=(Builder&&) noexcept -> Builder& = default;
|
||||
|
||||
// Adds a note diagnostic attached to the main diagnostic being built.
|
||||
// The API mirrors the main emission API: `Emitter::Emit`.
|
||||
// For the expected usage see the builder API: `Emitter::Build`.
|
||||
template <typename... Args>
|
||||
auto Note(LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder&;
|
||||
Internal::NoTypeDeduction<Args>... args) -> Builder&;
|
||||
|
||||
// Emits the built diagnostic and its attached notes.
|
||||
// For the expected usage see the builder API: `Emitter::Build`.
|
||||
@@ -92,7 +91,7 @@ class Emitter {
|
||||
template <typename... Args>
|
||||
auto Emit() && -> void;
|
||||
|
||||
// Returns true if this DiagnosticBuilder may emit a diagnostic. Can be used
|
||||
// Returns true if this Builder may emit a diagnostic. Can be used
|
||||
// to avoid excess work computing notes, etc, if no diagnostic is going to
|
||||
// be emitted anyway.
|
||||
explicit operator bool() { return emitter_; }
|
||||
@@ -101,13 +100,13 @@ class Emitter {
|
||||
friend class Emitter<LocT>;
|
||||
|
||||
template <typename... Args>
|
||||
explicit DiagnosticBuilder(Emitter<LocT>* emitter, LocT loc,
|
||||
const DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args);
|
||||
explicit Builder(Emitter<LocT>* emitter, LocT loc,
|
||||
const DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args);
|
||||
|
||||
// Create a null `DiagnosticBuilder` that will not emit anything. Notes will
|
||||
// Create a null `Builder` that will not emit anything. Notes will
|
||||
// be silently ignored.
|
||||
DiagnosticBuilder() : emitter_(nullptr) {}
|
||||
Builder() : emitter_(nullptr) {}
|
||||
|
||||
// Adds a message to the diagnostic, handling conversion of the location and
|
||||
// arguments.
|
||||
@@ -156,11 +155,11 @@ class Emitter {
|
||||
// .Emit();
|
||||
template <typename... Args>
|
||||
auto Build(LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder;
|
||||
Internal::NoTypeDeduction<Args>... args) -> Builder;
|
||||
|
||||
// Create a null `DiagnosticBuilder` that will not emit anything. Notes will
|
||||
// Create a null `Builder` that will not emit anything. Notes will
|
||||
// be silently ignored.
|
||||
auto BuildSuppressed() -> DiagnosticBuilder { return DiagnosticBuilder(); }
|
||||
auto BuildSuppressed() -> Builder { return Builder(); }
|
||||
|
||||
protected:
|
||||
// Callback type used to report context messages from ConvertLoc.
|
||||
@@ -189,7 +188,7 @@ class Emitter {
|
||||
friend class AnnotationScope;
|
||||
|
||||
Consumer* consumer_;
|
||||
llvm::SmallVector<llvm::function_ref<auto(DiagnosticBuilder& builder)->void>>
|
||||
llvm::SmallVector<llvm::function_ref<auto(Builder& builder)->void>>
|
||||
annotate_fns_;
|
||||
};
|
||||
|
||||
@@ -223,7 +222,7 @@ class NoLocEmitter : public Emitter<void*> {
|
||||
// be annotated in some way.
|
||||
//
|
||||
// This object is given a function `annotate` that will be called with a
|
||||
// `DiagnosticBuilder& builder` for any diagnostic that is emitted through the
|
||||
// `Builder& builder` for any diagnostic that is emitted through the
|
||||
// given emitter. That function can annotate the diagnostic by calling
|
||||
// `builder.Note` to add notes.
|
||||
template <typename LocT, typename AnnotateFn>
|
||||
@@ -269,9 +268,9 @@ struct DiagnosticTypeForArg<Arg> : public Arg::DiagnosticType {};
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto Emitter<LocT>::DiagnosticBuilder::Note(
|
||||
auto Emitter<LocT>::Builder::Note(
|
||||
LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> DiagnosticBuilder& {
|
||||
Internal::NoTypeDeduction<Args>... args) -> Builder& {
|
||||
if (!emitter_) {
|
||||
return *this;
|
||||
}
|
||||
@@ -284,7 +283,7 @@ auto Emitter<LocT>::DiagnosticBuilder::Note(
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto Emitter<LocT>::DiagnosticBuilder::Emit() & -> void {
|
||||
auto Emitter<LocT>::Builder::Emit() & -> void {
|
||||
if (!emitter_) {
|
||||
return;
|
||||
}
|
||||
@@ -301,7 +300,7 @@ concept AlwaysFalse = false;
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto Emitter<LocT>::DiagnosticBuilder::Emit() && -> void {
|
||||
auto Emitter<LocT>::Builder::Emit() && -> void {
|
||||
// TODO: This is required by clang-16, but `false` may work in newer clang
|
||||
// versions. Replace when possible.
|
||||
static_assert(Internal::AlwaysFalse<LocT>,
|
||||
@@ -312,10 +311,9 @@ auto Emitter<LocT>::DiagnosticBuilder::Emit() && -> void {
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
Emitter<LocT>::DiagnosticBuilder::DiagnosticBuilder(
|
||||
Emitter<LocT>* emitter, LocT loc,
|
||||
const DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args)
|
||||
Emitter<LocT>::Builder::Builder(Emitter<LocT>* emitter, LocT loc,
|
||||
const DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args)
|
||||
: emitter_(emitter), diagnostic_({.level = diagnostic_base.Level}) {
|
||||
AddMessage(loc, diagnostic_base, std::move(args));
|
||||
CARBON_CHECK(diagnostic_base.Level != Level::Note);
|
||||
@@ -323,7 +321,7 @@ Emitter<LocT>::DiagnosticBuilder::DiagnosticBuilder(
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto Emitter<LocT>::DiagnosticBuilder::AddMessage(
|
||||
auto Emitter<LocT>::Builder::AddMessage(
|
||||
LocT loc, const DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args) -> void {
|
||||
if (!emitter_) {
|
||||
@@ -343,7 +341,7 @@ auto Emitter<LocT>::DiagnosticBuilder::AddMessage(
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto Emitter<LocT>::DiagnosticBuilder::AddMessageWithLoc(
|
||||
auto Emitter<LocT>::Builder::AddMessageWithLoc(
|
||||
Loc loc, const DiagnosticBase<Args...>& diagnostic_base,
|
||||
llvm::SmallVector<llvm::Any> args) -> void {
|
||||
if (!emitter_) {
|
||||
@@ -363,8 +361,8 @@ auto Emitter<LocT>::DiagnosticBuilder::AddMessageWithLoc(
|
||||
|
||||
template <typename LocT>
|
||||
template <typename... Args, size_t... N>
|
||||
auto Emitter<LocT>::DiagnosticBuilder::FormatFn(
|
||||
const Message& message, std::index_sequence<N...> /*indices*/)
|
||||
auto Emitter<LocT>::Builder::FormatFn(const Message& message,
|
||||
std::index_sequence<N...> /*indices*/)
|
||||
-> std::string {
|
||||
static_assert(sizeof...(Args) == sizeof...(N), "Invalid template args");
|
||||
CARBON_CHECK(message.format_args.size() == sizeof...(Args),
|
||||
@@ -382,8 +380,7 @@ template <typename... Args>
|
||||
auto Emitter<LocT>::Emit(LocT loc,
|
||||
const DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args) -> void {
|
||||
DiagnosticBuilder builder(this, loc, diagnostic_base,
|
||||
{MakeAny<Args>(args)...});
|
||||
Builder builder(this, loc, diagnostic_base, {MakeAny<Args>(args)...});
|
||||
builder.Emit();
|
||||
}
|
||||
|
||||
@@ -391,10 +388,8 @@ template <typename LocT>
|
||||
template <typename... Args>
|
||||
auto Emitter<LocT>::Build(LocT loc,
|
||||
const DiagnosticBase<Args...>& diagnostic_base,
|
||||
Internal::NoTypeDeduction<Args>... args)
|
||||
-> DiagnosticBuilder {
|
||||
return DiagnosticBuilder(this, loc, diagnostic_base,
|
||||
{MakeAny<Args>(args)...});
|
||||
Internal::NoTypeDeduction<Args>... args) -> Builder {
|
||||
return Builder(this, loc, diagnostic_base, {MakeAny<Args>(args)...});
|
||||
}
|
||||
|
||||
template <typename LocT>
|
||||
|
||||
@@ -19,15 +19,16 @@
|
||||
|
||||
namespace Carbon::LanguageServer {
|
||||
|
||||
namespace {
|
||||
// A consumer for turning diagnostics into a `textDocument/publishDiagnostics`
|
||||
// notification.
|
||||
// https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_publishDiagnostics
|
||||
class PublishDiagnosticConsumer : public Diagnostics::Consumer {
|
||||
class DiagnosticConsumer : public Diagnostics::Consumer {
|
||||
public:
|
||||
// Initializes params with the target file information.
|
||||
explicit PublishDiagnosticConsumer(Context* context,
|
||||
const clang::clangd::URIForFile& uri,
|
||||
std::optional<int64_t> version)
|
||||
explicit DiagnosticConsumer(Context* context,
|
||||
const clang::clangd::URIForFile& uri,
|
||||
std::optional<int64_t> version)
|
||||
: context_(context), params_{.uri = uri, .version = version} {}
|
||||
|
||||
// Turns a diagnostic into an LSP diagnostic.
|
||||
@@ -98,6 +99,7 @@ class PublishDiagnosticConsumer : public Diagnostics::Consumer {
|
||||
Context* context_;
|
||||
clang::clangd::PublishDiagnosticsParams params_;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
auto Context::File::SetText(Context& context, std::optional<int64_t> version,
|
||||
llvm::StringRef text) -> void {
|
||||
@@ -109,7 +111,7 @@ auto Context::File::SetText(Context& context, std::optional<int64_t> version,
|
||||
source_.reset();
|
||||
|
||||
// A consumer to gather diagnostics for the file.
|
||||
PublishDiagnosticConsumer consumer(&context, uri_, version);
|
||||
DiagnosticConsumer consumer(&context, uri_, version);
|
||||
|
||||
// TODO: Make the processing asynchronous, to better handle rapid text
|
||||
// updates.
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
namespace Carbon::Lex {
|
||||
|
||||
using LexerDiagnosticEmitter = Diagnostics::Emitter<const char*>;
|
||||
using DiagnosticEmitter = Diagnostics::Emitter<const char*>;
|
||||
|
||||
static constexpr char MultiLineIndicator[] = R"(''')";
|
||||
static constexpr char DoubleQuotedMultiLineIndicator[] = R"(""")";
|
||||
@@ -202,7 +202,7 @@ static auto ComputeIndentOfFinalLine(llvm::StringRef text) -> llvm::StringRef {
|
||||
// Check the literal is indented properly, if it's a multi-line litera.
|
||||
// Find the leading whitespace that should be removed from each line of a
|
||||
// multi-line string literal.
|
||||
static auto CheckIndent(LexerDiagnosticEmitter& emitter, llvm::StringRef text,
|
||||
static auto CheckIndent(DiagnosticEmitter& emitter, llvm::StringRef text,
|
||||
llvm::StringRef content) -> llvm::StringRef {
|
||||
// Find the leading horizontal whitespace on the final line of this literal.
|
||||
// Note that for an empty literal, this might not be inside the content.
|
||||
@@ -222,7 +222,7 @@ static auto CheckIndent(LexerDiagnosticEmitter& emitter, llvm::StringRef text,
|
||||
}
|
||||
|
||||
// Expand a `\u{HHHHHH}` escape sequence into a sequence of UTF-8 code units.
|
||||
static auto ExpandUnicodeEscapeSequence(LexerDiagnosticEmitter& emitter,
|
||||
static auto ExpandUnicodeEscapeSequence(DiagnosticEmitter& emitter,
|
||||
llvm::StringRef digits,
|
||||
char*& buffer_cursor) -> bool {
|
||||
unsigned code_point;
|
||||
@@ -279,7 +279,7 @@ static auto AppendFrontOfContents(char*& buffer_cursor,
|
||||
// `result` string. `content` is the string content, starting from the first
|
||||
// character after the escape sequence introducer (for example, the `n` in
|
||||
// `\n`), and will be updated to remove the leading escape sequence.
|
||||
static auto ExpandAndConsumeEscapeSequence(LexerDiagnosticEmitter& emitter,
|
||||
static auto ExpandAndConsumeEscapeSequence(DiagnosticEmitter& emitter,
|
||||
llvm::StringRef& content,
|
||||
char*& buffer_cursor) -> void {
|
||||
CARBON_CHECK(!content.empty(), "should have escaped closing delimiter");
|
||||
@@ -364,7 +364,7 @@ static auto ExpandAndConsumeEscapeSequence(LexerDiagnosticEmitter& emitter,
|
||||
|
||||
// Expand any escape sequences in the given string literal.
|
||||
static auto ExpandEscapeSequencesAndRemoveIndent(
|
||||
LexerDiagnosticEmitter& emitter, llvm::StringRef contents, int hash_level,
|
||||
DiagnosticEmitter& emitter, llvm::StringRef contents, int hash_level,
|
||||
llvm::StringRef indent, char* buffer) -> llvm::StringRef {
|
||||
char* buffer_cursor = buffer;
|
||||
|
||||
@@ -464,7 +464,7 @@ static auto ExpandEscapeSequencesAndRemoveIndent(
|
||||
}
|
||||
|
||||
auto StringLiteral::ComputeValue(llvm::BumpPtrAllocator& allocator,
|
||||
LexerDiagnosticEmitter& emitter) const
|
||||
DiagnosticEmitter& emitter) const
|
||||
-> llvm::StringRef {
|
||||
if (!is_terminated_) {
|
||||
return "";
|
||||
|
||||
@@ -17,7 +17,6 @@ cc_library(
|
||||
hdrs = ["lower.h"],
|
||||
deps = [
|
||||
":context",
|
||||
"//toolchain/check:sem_ir_loc_diagnostic_emitter",
|
||||
"//toolchain/parse:tree",
|
||||
"//toolchain/sem_ir:file",
|
||||
"//toolchain/sem_ir:inst_namer",
|
||||
@@ -50,7 +49,7 @@ cc_library(
|
||||
"//common:raw_string_ostream",
|
||||
"//common:vlog",
|
||||
"//toolchain/base:kind_switch",
|
||||
"//toolchain/check:sem_ir_loc_diagnostic_emitter",
|
||||
"//toolchain/parse:tree",
|
||||
"//toolchain/sem_ir:absolute_node_id",
|
||||
"//toolchain/sem_ir:entry_point",
|
||||
"//toolchain/sem_ir:file",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "llvm/IR/DIBuilder.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "toolchain/check/sem_ir_loc_diagnostic_emitter.h"
|
||||
#include "toolchain/parse/tree_and_subtrees.h"
|
||||
#include "toolchain/sem_ir/file.h"
|
||||
#include "toolchain/sem_ir/ids.h"
|
||||
#include "toolchain/sem_ir/inst_namer.h"
|
||||
|
||||
@@ -35,9 +35,10 @@ enum class Lookahead : int32_t {
|
||||
class Context {
|
||||
public:
|
||||
// A token-based emitter for use during parse.
|
||||
class TokenEmitter : public Diagnostics::Emitter<Lex::TokenIndex> {
|
||||
class DiagnosticEmitter : public Diagnostics::Emitter<Lex::TokenIndex> {
|
||||
public:
|
||||
explicit TokenEmitter(Diagnostics::Consumer* consumer, Context* context)
|
||||
explicit DiagnosticEmitter(Diagnostics::Consumer* consumer,
|
||||
Context* context)
|
||||
: Emitter(consumer), context_(context) {}
|
||||
|
||||
protected:
|
||||
@@ -407,7 +408,7 @@ class Context {
|
||||
|
||||
auto has_errors() const -> bool { return err_tracker_.seen_error(); }
|
||||
|
||||
auto emitter() -> TokenEmitter& { return emitter_; }
|
||||
auto emitter() -> DiagnosticEmitter& { return emitter_; }
|
||||
|
||||
auto position() -> Lex::TokenIterator& { return position_; }
|
||||
auto position() const -> Lex::TokenIterator { return position_; }
|
||||
@@ -441,7 +442,7 @@ class Context {
|
||||
Lex::TokenizedBuffer* tokens_;
|
||||
|
||||
Diagnostics::ErrorTrackingConsumer err_tracker_;
|
||||
TokenEmitter emitter_;
|
||||
DiagnosticEmitter emitter_;
|
||||
|
||||
// Whether to print verbose output.
|
||||
llvm::raw_ostream* vlog_stream_;
|
||||
|
||||
Reference in New Issue
Block a user