mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:40:12 +01:00
I've been mulling this mainly for the parameter complexity of check/lower, but doing lex/parse for symmetry. I'm motivated by the plan to move dumping for all of them into the respective functions, because of discussion about llvm-verifier. That basically would add another bool parameter (or more) to each of these. My instinct is we're going to probably accrue a little more over time, so I'm suggesting this as maybe adding the boundary a little simpler and/or easier to read. Note it may make sense to refactor a little further, e.g. maybe Lower::Context could receive the full set of options and pick out what it wants, but I figured creating the struct itself would be a decent start. I'm trying to put things into options when we can produce a reasonable default if the user doesn't assign a value. I'm using an explicit constructor so that values can be added without affecting every caller. A different factoring would be to pass in everything through the param struct, but that just felt weird when I was trying it out. Removing `inst_namer` and `module_name` from `LowerToLLVM` params -- both of these can be inferred from `sem_ir`, and I'm not seeing a particular reason to maintain them at the call site.
106 lines
3.1 KiB
C++
106 lines
3.1 KiB
C++
// 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/format_subcommand.h"
|
|
|
|
#include <string>
|
|
|
|
#include "common/raw_string_ostream.h"
|
|
#include "toolchain/base/shared_value_stores.h"
|
|
#include "toolchain/diagnostics/diagnostic_consumer.h"
|
|
#include "toolchain/format/format.h"
|
|
#include "toolchain/lex/lex.h"
|
|
#include "toolchain/source/source_buffer.h"
|
|
|
|
namespace Carbon {
|
|
|
|
auto FormatOptions::Build(CommandLine::CommandBuilder& b) -> void {
|
|
b.AddStringPositionalArg(
|
|
{
|
|
.name = "FILE",
|
|
.help = R"""(
|
|
The input Carbon source file(s) to format.
|
|
)""",
|
|
},
|
|
[&](auto& arg_b) {
|
|
arg_b.Required(true);
|
|
arg_b.Append(&input_filenames);
|
|
});
|
|
b.AddStringOption(
|
|
{
|
|
.name = "output",
|
|
.value_name = "FILE",
|
|
.help = R"""(
|
|
The output filename for formatted output.
|
|
|
|
By default, the input file is formatted. Passing `--output=-` will write the
|
|
output to stdout.
|
|
|
|
Not valid when multiple files are passed for formatting.
|
|
)""",
|
|
},
|
|
[&](auto& arg_b) { arg_b.Set(&output_filename); });
|
|
}
|
|
|
|
static constexpr CommandLine::CommandInfo SubcommandInfo = {
|
|
.name = "format",
|
|
.help = R"""(
|
|
Format Carbon source code.
|
|
)""",
|
|
};
|
|
|
|
FormatSubcommand::FormatSubcommand() : DriverSubcommand(SubcommandInfo) {}
|
|
|
|
auto FormatSubcommand::Run(DriverEnv& driver_env) -> DriverResult {
|
|
DriverResult result = {.success = true};
|
|
if (options_.input_filenames.size() > 1 &&
|
|
!options_.output_filename.empty()) {
|
|
CARBON_DIAGNOSTIC(FormatMultipleFilesToOneOutput, Error,
|
|
"multiple input files are being provided; --output only "
|
|
"works with one input");
|
|
driver_env.emitter.Emit(FormatMultipleFilesToOneOutput);
|
|
result.success = false;
|
|
return result;
|
|
}
|
|
|
|
auto mark_per_file_error = [&]() {
|
|
result.success = false;
|
|
result.per_file_success.back().second = false;
|
|
};
|
|
|
|
for (auto& f : options_.input_filenames) {
|
|
// Push a result, which we'll update on failure.
|
|
result.per_file_success.push_back({f.str(), true});
|
|
|
|
// TODO: Consider refactoring this for sharing with compile.
|
|
// TODO: Decide what to do with `-` when there are multiple arguments.
|
|
auto source = SourceBuffer::MakeFromFileOrStdin(*driver_env.fs, f,
|
|
driver_env.consumer);
|
|
if (!source) {
|
|
mark_per_file_error();
|
|
continue;
|
|
}
|
|
SharedValueStores value_stores;
|
|
Lex::LexOptions lex_options;
|
|
lex_options.consumer = &driver_env.consumer;
|
|
auto tokens = Lex::Lex(value_stores, *source, lex_options);
|
|
|
|
RawStringOstream buffer;
|
|
if (Format::Format(tokens, buffer)) {
|
|
// TODO: Figure out a multi-file output setup that supports good
|
|
// multi-file testing.
|
|
// TODO: Use --output values (and default to overwrite).
|
|
*driver_env.output_stream << buffer.TakeStr();
|
|
} else {
|
|
buffer.clear();
|
|
mark_per_file_error();
|
|
*driver_env.output_stream << source->text();
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
} // namespace Carbon
|