Skip to content

Commit

Permalink
Move the language server into toolchain's busybox. (#4469)
Browse files Browse the repository at this point in the history
Removes the separate language server binary; I'm not sure we need to
provide it. Instead, `carbon language-server` is added as a subcommand.

Moves //language_server to //toolchain/language_server. Splits into a
trivial language_server.h, and a substantive server.h. I wasn't sure
about a better name, but wanted the split similar to check/check.h,
lex/lex.h, etc. At the same time, the class is probably going to be a
little big so not a good fit to through into just a cpp file.

This fixes some style issues with the language server class, but
generally I'm trying to not address things here in order to keep it
simpler.
  • Loading branch information
jonmeow authored Nov 1, 2024
1 parent 954441c commit 145c44b
Show file tree
Hide file tree
Showing 17 changed files with 197 additions and 94 deletions.
1 change: 0 additions & 1 deletion .github/workflows/auto_label_prs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ jobs:
toolchain:
- 'common/**'
- 'core/**'
- 'language_server/**'
- 'testing/**'
- 'toolchain/**'
Expand Down
1 change: 0 additions & 1 deletion bazel/check_deps/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ filegroup(
data = [
"//explorer",
"//installers/local:carbon",
"//language_server",
"//migrate_cpp:rewriter",
"//migrate_cpp/cpp_refactoring",
"//toolchain/install:carbon-busybox",
Expand Down
10 changes: 0 additions & 10 deletions language_server/main.cpp

This file was deleted.

3 changes: 3 additions & 0 deletions toolchain/driver/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ cc_library(
"driver_env.h",
"format_subcommand.cpp",
"format_subcommand.h",
"language_server_subcommand.cpp",
"language_server_subcommand.h",
"link_subcommand.cpp",
"link_subcommand.h",
],
Expand All @@ -116,6 +118,7 @@ cc_library(
"//toolchain/diagnostics:sorting_diagnostic_consumer",
"//toolchain/format",
"//toolchain/install:install_paths",
"//toolchain/language_server",
"//toolchain/lex",
"//toolchain/lower",
"//toolchain/parse",
Expand Down
7 changes: 7 additions & 0 deletions toolchain/driver/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "toolchain/driver/clang_subcommand.h"
#include "toolchain/driver/compile_subcommand.h"
#include "toolchain/driver/format_subcommand.h"
#include "toolchain/driver/language_server_subcommand.h"
#include "toolchain/driver/link_subcommand.h"

namespace Carbon {
Expand All @@ -29,6 +30,7 @@ struct Options {
ClangSubcommand clang;
CompileSubcommand compile;
FormatSubcommand format;
LanguageServerSubcommand language_server;
LinkSubcommand link;

// On success, this is set to the subcommand to run.
Expand Down Expand Up @@ -87,6 +89,11 @@ auto Options::Build(CommandLine::CommandBuilder& b) -> void {
sub_b.Do([&] { subcommand = &format; });
});

b.AddSubcommand(LanguageServerSubcommand::Info,
[&](CommandLine::CommandBuilder& sub_b) {
sub_b.Do([&] { subcommand = &language_server; });
});

b.AddSubcommand(LinkOptions::Info, [&](CommandLine::CommandBuilder& sub_b) {
link.BuildOptions(sub_b);
sub_b.Do([&] { subcommand = &link; });
Expand Down
28 changes: 28 additions & 0 deletions toolchain/driver/language_server_subcommand.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// 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

#include "toolchain/driver/language_server_subcommand.h"

#include "toolchain/language_server/language_server.h"

namespace Carbon {

constexpr CommandLine::CommandInfo LanguageServerSubcommand::Info = {
.name = "language-server",
.help = R"""(
Runs the language server.
)""",
};

auto LanguageServerSubcommand::Run(DriverEnv& driver_env) -> DriverResult {
// TODO: Consider a way to override stdin, but it's a `FILE*` so less
// convenient to work with.
auto err = LanguageServer::Run(stdin, driver_env.output_stream);
if (!err.ok()) {
driver_env.error_stream << "error: " << err.error() << "\n";
}
return {.success = err.ok()};
}

} // namespace Carbon
27 changes: 27 additions & 0 deletions toolchain/driver/language_server_subcommand.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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_DRIVER_LANGUAGE_SERVER_SUBCOMMAND_H_
#define CARBON_TOOLCHAIN_DRIVER_LANGUAGE_SERVER_SUBCOMMAND_H_

#include "common/command_line.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "toolchain/driver/codegen_options.h"
#include "toolchain/driver/driver_env.h"
#include "toolchain/driver/driver_subcommand.h"

namespace Carbon {

// Implements the link subcommand of the driver.
class LanguageServerSubcommand : public DriverSubcommand {
public:
static const CommandLine::CommandInfo Info;

auto Run(DriverEnv& driver_env) -> DriverResult override;
};

} // namespace Carbon

#endif // CARBON_TOOLCHAIN_DRIVER_LANGUAGE_SERVER_SUBCOMMAND_H_
16 changes: 7 additions & 9 deletions language_server/BUILD → toolchain/language_server/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,23 @@
# Exceptions. See /LICENSE for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

load("@rules_cc//cc:defs.bzl", "cc_binary")
load("@rules_cc//cc:defs.bzl", "cc_library")

package(default_visibility = [
"//bazel/check_deps:__pkg__",
"//installers:__subpackages__",
"//language_server:__subpackages__",
])
package(default_visibility = ["//visibility:public"])

cc_binary(
cc_library(
name = "language_server",
srcs = [
"language_server.cpp",
"language_server.h",
"main.cpp",
"server.cpp",
"server.h",
],
hdrs = ["language_server.h"],
# Some parameters are unused in clangd headers.
copts = ["-Wno-unused-parameter"],
deps = [
"//common:error",
"//common:ostream",
"//toolchain/base:value_store",
"//toolchain/diagnostics:null_diagnostics",
"//toolchain/lex",
Expand Down
17 changes: 17 additions & 0 deletions toolchain/language_server/language_server.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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

#include "toolchain/language_server/language_server.h"

#include "toolchain/language_server/server.h"

namespace Carbon::LanguageServer {

auto Run(std::FILE* input_stream, llvm::raw_ostream& output_stream)
-> ErrorOr<Success> {
Server server(input_stream, output_stream);
return server.Run();
}

} // namespace Carbon::LanguageServer
19 changes: 19 additions & 0 deletions toolchain/language_server/language_server.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// 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_LANGUAGE_SERVER_H_
#define CARBON_TOOLCHAIN_LANGUAGE_SERVER_LANGUAGE_SERVER_H_

#include "common/error.h"
#include "common/ostream.h"

namespace Carbon::LanguageServer {

// Start the language server.
auto Run(std::FILE* input_stream, llvm::raw_ostream& output_stream)
-> ErrorOr<Success>;

} // namespace Carbon::LanguageServer

#endif // CARBON_TOOLCHAIN_LANGUAGE_SERVER_LANGUAGE_SERVER_H_
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "language_server/language_server.h"
#include "toolchain/language_server/server.h"

#include "clang-tools-extra/clangd/Protocol.h"
#include "toolchain/base/value_store.h"
#include "toolchain/diagnostics/null_diagnostics.h"
#include "toolchain/lex/lex.h"
Expand All @@ -13,22 +12,48 @@
#include "toolchain/parse/tree_and_subtrees.h"
#include "toolchain/source/source_buffer.h"

namespace Carbon::LS {
namespace Carbon::LanguageServer {

Server::Server(std::FILE* input_stream, llvm::raw_ostream& output_stream)
: transport_(clang::clangd::newJSONTransport(input_stream, output_stream,
/*InMirror=*/nullptr,
/*Pretty=*/true)),
binder_(handlers_, *this) {
binder_.notification("textDocument/didOpen", this,
&Server::OnDidOpenTextDocument);
binder_.notification("textDocument/didChange", this,
&Server::OnDidChangeTextDocument);
binder_.method("initialize", this, &Server::OnInitialize);
binder_.method("textDocument/documentSymbol", this,
&Server::OnDocumentSymbol);
}

auto Server::Run() -> ErrorOr<Success> {
llvm::Error err = transport_->loop(*this);
if (err.success()) {
return Success();
} else {
std::string str;
llvm::raw_string_ostream out(str);
out << err;
return Error(str);
}
}

void LanguageServer::OnDidOpenTextDocument(
void Server::OnDidOpenTextDocument(
clang::clangd::DidOpenTextDocumentParams const& params) {
files_.emplace(params.textDocument.uri.file(), params.textDocument.text);
}

void LanguageServer::OnDidChangeTextDocument(
void Server::OnDidChangeTextDocument(
clang::clangd::DidChangeTextDocumentParams const& params) {
// full text is sent if full sync is specified in capabilities.
assert(params.contentChanges.size() == 1);
// Full text is sent if full sync is specified in capabilities.
CARBON_CHECK(params.contentChanges.size() == 1);
std::string file = params.textDocument.uri.file().str();
files_[file] = params.contentChanges[0].text;
}

void LanguageServer::OnInitialize(
void Server::OnInitialize(
clang::clangd::NoParams const& /*client_capabilities*/,
clang::clangd::Callback<llvm::json::Object> cb) {
llvm::json::Object capabilities{{"documentSymbolProvider", true},
Expand All @@ -38,8 +63,7 @@ void LanguageServer::OnInitialize(
cb(reply);
}

auto LanguageServer::onNotify(llvm::StringRef method, llvm::json::Value value)
-> bool {
auto Server::onNotify(llvm::StringRef method, llvm::json::Value value) -> bool {
if (method == "exit") {
return false;
}
Expand All @@ -53,8 +77,8 @@ auto LanguageServer::onNotify(llvm::StringRef method, llvm::json::Value value)
return true;
}

auto LanguageServer::onCall(llvm::StringRef method, llvm::json::Value params,
llvm::json::Value id) -> bool {
auto Server::onCall(llvm::StringRef method, llvm::json::Value params,
llvm::json::Value id) -> bool {
if (auto handler = handlers_.MethodHandlers.find(method);
handler != handlers_.MethodHandlers.end()) {
// TODO: improve this if add threads
Expand All @@ -71,9 +95,8 @@ auto LanguageServer::onCall(llvm::StringRef method, llvm::json::Value params,
return true;
}

auto LanguageServer::onReply(llvm::json::Value /*id*/,
llvm::Expected<llvm::json::Value> /*result*/)
-> bool {
auto Server::onReply(llvm::json::Value /*id*/,
llvm::Expected<llvm::json::Value> /*result*/) -> bool {
return true;
}

Expand All @@ -94,7 +117,7 @@ static auto GetIdentifierName(const SharedValueStores& value_stores,
return std::nullopt;
}

void LanguageServer::OnDocumentSymbol(
void Server::OnDocumentSymbol(
clang::clangd::DocumentSymbolParams const& params,
clang::clangd::Callback<std::vector<clang::clangd::DocumentSymbol>> cb) {
SharedValueStores value_stores;
Expand Down Expand Up @@ -148,19 +171,4 @@ void LanguageServer::OnDocumentSymbol(
cb(result);
}

void LanguageServer::Start() {
auto transport =
clang::clangd::newJSONTransport(stdin, llvm::outs(), nullptr, true);
LanguageServer ls(std::move(transport));
clang::clangd::LSPBinder binder(ls.handlers_, ls);
binder.notification("textDocument/didOpen", &ls,
&LanguageServer::OnDidOpenTextDocument);
binder.notification("textDocument/didChange", &ls,
&LanguageServer::OnDidChangeTextDocument);
binder.method("initialize", &ls, &LanguageServer::OnInitialize);
binder.method("textDocument/documentSymbol", &ls,
&LanguageServer::OnDocumentSymbol);
auto error = ls.transport_->loop(ls);
llvm::errs() << "Error: " << error << "\n";
}
} // namespace Carbon::LS
} // namespace Carbon::LanguageServer
Loading

0 comments on commit 145c44b

Please sign in to comment.