Repository: carbon-language/carbon-lang
File: toolchain/language_server/language_server.cpp (C++)

Code before:
                  llvm::raw_ostream* vlog_stream)
      : error_logger_(*error_stream, clang::clangd::Logger::Info),
        vlog_logger_(vlog_stream
                         ? std::make_unique<clang::clangd::StreamLogger>(
                               *vlog_stream, clang::clangd::Logger::Verbose)
                         : nullptr) {}

  auto log(Level level, const char* format,
           const llvm::formatv_object_base& message) -> void override {
    if (level != clang::clangd::Logger::Verbose) {
      error_logger_.log(level, format, message);
    } else if (vlog_logger_) {
      vlog_logger_->log(level, format, message);
    }
  }

 private:
  clang::clangd::StreamLogger error_logger_;
  std::unique_ptr<clang::clangd::StreamLogger> vlog_logger_;
};

auto Run(FILE* input_stream, llvm::raw_ostream& output_stream,
         llvm::raw_ostream& error_stream, llvm::raw_ostream* vlog_stream,
         FilenameDiagnosticEmitter& emitter) -> bool {
  // The language server internally uses diagnostics for logging issues, but the
  // clangd parts have their own logging system. We intercept that here.
  Logger logger(&error_stream, vlog_stream);
  clang::clangd::LoggingSession logging_session(logger);

  // Set up the connection.
  std::unique_ptr<clang::clangd::Transport> transport(
      clang::clangd::newJSONTransport(input_stream, output_stream,
                                      /*InMirror=*/nullptr,
                                      /*Pretty=*/true));
  Context context(&emitter);
  // TODO: Use error_stream in IncomingMessages to report dropped errors.
  IncomingMessages incoming(transport.get(), &context);
  OutgoingMessages outgoing(transport.get());

  // Run the server loop.
  llvm::Error err = transport->loop(incoming);
  if (err) {
    RawStringOstream out;
    out << err;
    CARBON_DIAGNOSTIC(LanguageServerTransportError, Error, "{0}", std::string);
    emitter.Emit("", LanguageServerTransportError, out.TakeStr());
    return false;
  }
  return true;
}


Review comment (suggestion):
Is using diagnostics internally the right thing here?

Specifically, do we need to do anything to avoid internal language server errors showing up in the IDE's UI because we emit them using our diagnostic infrastructure? Maybe the UIs actually handle these diagnostics well? Or maybe there is a way to consume them and print them to the streams instead of sending them back?

Sorry if this is just lack of context on my part -- and not sure it's really blocking, just a bit curious about the strategy here.

Code after:
  explicit Logger(llvm::raw_ostream* error_stream,
                  llvm::raw_ostream* vlog_stream)
      : error_logger_(*error_stream, clang::clangd::Logger::Info),
        vlog_logger_(vlog_stream
                         ? std::make_unique<clang::clangd::StreamLogger>(
                               *vlog_stream, clang::clangd::Logger::Verbose)
                         : nullptr) {}

  auto log(Level level, const char* format,
           const llvm::formatv_object_base& message) -> void override {
    if (level != clang::clangd::Logger::Verbose) {
      error_logger_.log(level, format, message);
    } else if (vlog_logger_) {
      vlog_logger_->log(level, format, message);
    }
  }

 private:
  clang::clangd::StreamLogger error_logger_;
  std::unique_ptr<clang::clangd::StreamLogger> vlog_logger_;
};

auto Run(FILE* input_stream, llvm::raw_ostream& output_stream,
         llvm::raw_ostream& error_stream, llvm::raw_ostream* vlog_stream,
         DiagnosticConsumer& consumer) -> bool {
  // The language server internally uses diagnostics for logging issues, but the
  // clangd parts have their own logging system. We intercept that here.
  Logger logger(&error_stream, vlog_stream);
  clang::clangd::LoggingSession logging_session(logger);

  // Set up the connection.
  std::unique_ptr<clang::clangd::Transport> transport(
      clang::clangd::newJSONTransport(input_stream, output_stream,
                                      /*InMirror=*/nullptr,
                                      /*Pretty=*/true));
  Context context(&consumer);
  // TODO: Use error_stream in IncomingMessages to report dropped errors.
  IncomingMessages incoming(transport.get(), &context);
  OutgoingMessages outgoing(transport.get());

  // Run the server loop.
  llvm::Error err = transport->loop(incoming);
  if (err) {
    RawStringOstream out;
    out << err;
    CARBON_DIAGNOSTIC(LanguageServerTransportError, Error, "{0}", std::string);
    NoLocDiagnosticEmitter emitter(&consumer);
    emitter.Emit(LanguageServerTransportError, out.TakeStr());
    return false;
  }
  return true;