diff --git a/toolchain/driver/language_server_subcommand.cpp b/toolchain/driver/language_server_subcommand.cpp index 6a52f81882c8..a218b9e3f113 100644 --- a/toolchain/driver/language_server_subcommand.cpp +++ b/toolchain/driver/language_server_subcommand.cpp @@ -19,6 +19,21 @@ Runs the language server. LanguageServerSubcommand::LanguageServerSubcommand() : DriverSubcommand(SubcommandInfo) {} +auto LanguageServerSubcommand::BuildOptions(CommandLine::CommandBuilder& b) + -> void { + b.AddFlag( + { + .name = "prelude-import", + .help = R"""( +Whether to use the implicit prelude import. Enabled by default. +)""", + }, + [&](auto& arg_b) { + arg_b.Default(true); + arg_b.Set(&prelude_import_); + }); +} + auto LanguageServerSubcommand::Run(DriverEnv& driver_env) -> DriverResult { if (!driver_env.input_stream) { CARBON_DIAGNOSTIC(LanguageServerMissingInputStream, Error, @@ -27,10 +42,10 @@ auto LanguageServerSubcommand::Run(DriverEnv& driver_env) -> DriverResult { return {.success = false}; } - bool success = - LanguageServer::Run(*driver_env.installation, driver_env.input_stream, - *driver_env.output_stream, *driver_env.error_stream, - driver_env.vlog_stream, *driver_env.consumer); + bool success = LanguageServer::Run( + *driver_env.installation, driver_env.input_stream, + *driver_env.output_stream, *driver_env.error_stream, + driver_env.vlog_stream, *driver_env.consumer, prelude_import_); return {.success = success}; } diff --git a/toolchain/driver/language_server_subcommand.h b/toolchain/driver/language_server_subcommand.h index 73b1e6e5769a..489b3cc17938 100644 --- a/toolchain/driver/language_server_subcommand.h +++ b/toolchain/driver/language_server_subcommand.h @@ -14,14 +14,17 @@ namespace Carbon { -// Implements the link subcommand of the driver. +// Implements the language-server subcommand of the driver. class LanguageServerSubcommand : public DriverSubcommand { public: explicit LanguageServerSubcommand(); - auto BuildOptions(CommandLine::CommandBuilder& /*b*/) -> void override {} + auto BuildOptions(CommandLine::CommandBuilder& b) -> void override; auto Run(DriverEnv& driver_env) -> DriverResult override; + + private: + bool prelude_import_ = true; }; } // namespace Carbon diff --git a/toolchain/language_server/context.cpp b/toolchain/language_server/context.cpp index e895d823a48b..df58a4ba49ba 100644 --- a/toolchain/language_server/context.cpp +++ b/toolchain/language_server/context.cpp @@ -190,12 +190,14 @@ class VirtualFileSystem : public llvm::vfs::FileSystem { Context::Context(const InstallPaths* installation, llvm::raw_ostream* vlog_stream, Diagnostics::Consumer* consumer, - clang::clangd::LSPBinder::RawOutgoing* outgoing) + clang::clangd::LSPBinder::RawOutgoing* outgoing, + bool prelude_import) : installation_(installation), vlog_stream_(vlog_stream), file_emitter_(consumer), no_loc_emitter_(consumer), - outgoing_(outgoing) { + outgoing_(outgoing), + prelude_import_(prelude_import) { auto ls_fs = llvm::makeIntrusiveRefCnt(this); auto vfs = llvm::makeIntrusiveRefCnt( llvm::vfs::getRealFileSystem()); @@ -229,8 +231,8 @@ auto Context::File::SetText(Context& context, std::optional version, options_ = CompileOptions(); options_.codegen_options->target = options_.codegen_options->host; options_.phase = CompileOptions::Phase::Check; + options_.prelude_import = context.prelude_import(); options_.input_filenames.push_back(filename()); - options_.prelude_import = true; compile_driver_ = std::make_unique(&options_); auto map_input = [](llvm::StringRef) -> std::string { return ""; }; diff --git a/toolchain/language_server/context.h b/toolchain/language_server/context.h index 46a4c6251f63..1f4b813a64bc 100644 --- a/toolchain/language_server/context.h +++ b/toolchain/language_server/context.h @@ -59,7 +59,8 @@ class Context { explicit Context(const InstallPaths* installation, llvm::raw_ostream* vlog_stream, Diagnostics::Consumer* consumer, - clang::clangd::LSPBinder::RawOutgoing* outgoing); + clang::clangd::LSPBinder::RawOutgoing* outgoing, + bool prelude_import); // Returns the virtual filesystem. auto vfs() -> llvm::IntrusiveRefCntPtr& { @@ -86,6 +87,8 @@ class Context { auto files() -> Map& { return files_; } + auto prelude_import() const -> bool { return prelude_import_; } + private: const InstallPaths* installation_; @@ -100,6 +103,8 @@ class Context { // Content of files managed by the language client. Map files_; + + bool prelude_import_; }; } // namespace Carbon::LanguageServer diff --git a/toolchain/language_server/language_server.cpp b/toolchain/language_server/language_server.cpp index ab05c9e94a7f..6a3101adbaba 100644 --- a/toolchain/language_server/language_server.cpp +++ b/toolchain/language_server/language_server.cpp @@ -46,8 +46,8 @@ class Logger : public clang::clangd::Logger { auto Run(const InstallPaths& installation, FILE* input_stream, llvm::raw_ostream& output_stream, llvm::raw_ostream& error_stream, - llvm::raw_ostream* vlog_stream, Diagnostics::Consumer& consumer) - -> bool { + llvm::raw_ostream* vlog_stream, Diagnostics::Consumer& consumer, + bool prelude_import) -> 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); @@ -59,7 +59,8 @@ auto Run(const InstallPaths& installation, FILE* input_stream, /*InMirror=*/nullptr, /*Pretty=*/true)); OutgoingMessages outgoing(transport.get()); - Context context(&installation, vlog_stream, &consumer, &outgoing); + Context context(&installation, vlog_stream, &consumer, &outgoing, + prelude_import); IncomingMessages incoming(transport.get(), &context); // Run the server loop. diff --git a/toolchain/language_server/language_server.h b/toolchain/language_server/language_server.h index 3a4fb548d063..c7c99d79610e 100644 --- a/toolchain/language_server/language_server.h +++ b/toolchain/language_server/language_server.h @@ -18,8 +18,8 @@ namespace Carbon::LanguageServer { // This is thread-hostile because `clangd::LoggingSession` relies on a global. auto Run(const InstallPaths& installation, FILE* input_stream, llvm::raw_ostream& output_stream, llvm::raw_ostream& error_stream, - llvm::raw_ostream* vlog_stream, Diagnostics::Consumer& consumer) - -> bool; + llvm::raw_ostream* vlog_stream, Diagnostics::Consumer& consumer, + bool prelude_import) -> bool; } // namespace Carbon::LanguageServer diff --git a/toolchain/language_server/testdata/text_document/import_prelude.carbon b/toolchain/language_server/testdata/text_document/import_prelude.carbon index 4f6ac8144493..149c9c7a2519 100644 --- a/toolchain/language_server/testdata/text_document/import_prelude.carbon +++ b/toolchain/language_server/testdata/text_document/import_prelude.carbon @@ -2,6 +2,8 @@ // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // +// EXTRA-ARGS: --prelude-import +// // AUTOUPDATE // TIP: To test this file alone, run: // TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/language_server/testdata/text_document/import_prelude.carbon diff --git a/toolchain/testing/file_test.cpp b/toolchain/testing/file_test.cpp index 3aa60b2c4e06..946c8304d0f4 100644 --- a/toolchain/testing/file_test.cpp +++ b/toolchain/testing/file_test.cpp @@ -244,7 +244,7 @@ auto ToolchainFileTest::GetDefaultArgs() const args.insert(args.end(), {"format", "%s"}); return args; } else if (component_ == "language_server") { - args.insert(args.end(), {"language-server"}); + args.insert(args.end(), {"language-server", "--no-prelude-import"}); return args; }