Răsfoiți Sursa

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.
Jon Ross-Perkins 1 an în urmă
părinte
comite
0a3efb76ed

+ 4 - 4
toolchain/check/BUILD

@@ -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",

+ 1 - 1
toolchain/check/check.cpp

@@ -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"

+ 1 - 1
toolchain/check/check.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"

+ 2 - 2
toolchain/check/check_unit.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_;
 };
 

+ 1 - 1
toolchain/check/context.cpp

@@ -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)

+ 4 - 3
toolchain/check/context.h

@@ -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
toolchain/check/sem_ir_loc_diagnostic_emitter.cpp → toolchain/check/diagnostic_emitter.cpp

@@ -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
toolchain/check/sem_ir_loc_diagnostic_emitter.h → toolchain/check/diagnostic_emitter.h

@@ -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_

+ 6 - 2
toolchain/check/diagnostic_helpers.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

+ 1 - 3
toolchain/check/eval.cpp

@@ -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.

+ 1 - 1
toolchain/check/modifiers.cpp

@@ -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) {

+ 30 - 35
toolchain/diagnostics/diagnostic_emitter.h

@@ -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>

+ 7 - 5
toolchain/language_server/context.cpp

@@ -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.

+ 6 - 6
toolchain/lex/string_literal.cpp

@@ -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 "";

+ 1 - 2
toolchain/lower/BUILD

@@ -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",

+ 1 - 1
toolchain/lower/file_context.h

@@ -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"

+ 5 - 4
toolchain/parse/context.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_;