From ca947c0e4eae31c6a12a09c98bea4f1eb346a137 Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Fri, 31 May 2024 13:07:19 -0300 Subject: [PATCH] Implement `--fix` for the `lint` command Signed-off-by: Juan Cruz Viotti --- src/command_lint.cc | 44 +++++++++++++++++++++++++++++--------------- src/utils.cc | 8 ++++++-- test/CMakeLists.txt | 1 + test/lint_fix.sh | 28 ++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 17 deletions(-) create mode 100755 test/lint_fix.sh diff --git a/src/command_lint.cc b/src/command_lint.cc index a780c7da..49030d2c 100644 --- a/src/command_lint.cc +++ b/src/command_lint.cc @@ -2,15 +2,15 @@ #include #include // EXIT_SUCCESS +#include // std::ofstream #include // std::cerr, std::cout, std::endl #include "command.h" #include "utils.h" -// TODO: Implement a --fix flag auto intelligence::jsonschema::cli::lint( const std::span &arguments) -> int { - const auto options{parse_options(arguments, {})}; + const auto options{parse_options(arguments, {"f", "fix"})}; sourcemeta::jsontoolkit::SchemaTransformBundle bundle; bundle.add( @@ -19,19 +19,33 @@ auto intelligence::jsonschema::cli::lint( sourcemeta::jsontoolkit::SchemaTransformBundle::Category::AntiPattern); bool result{true}; - for (const auto &entry : for_each_json(options.at(""))) { - const bool subresult = bundle.check( - entry.second, sourcemeta::jsontoolkit::default_schema_walker, - resolver(options), - [&entry](const auto &pointer, const auto &name, const auto &message) { - std::cout << entry.first.string() << "\n"; - std::cout << " "; - sourcemeta::jsontoolkit::stringify(pointer, std::cout); - std::cout << " " << message << " (" << name << ")\n"; - }); - - if (!subresult) { - result = false; + + if (options.contains("f") || options.contains("fix")) { + for (const auto &entry : for_each_json(options.at(""))) { + log_verbose(options) << "Linting: " << entry.first.string() << "\n"; + auto copy = entry.second; + bundle.apply(copy, sourcemeta::jsontoolkit::default_schema_walker, + resolver(options)); + std::ofstream output{entry.first}; + sourcemeta::jsontoolkit::prettify( + copy, output, sourcemeta::jsontoolkit::schema_format_compare); + output << std::endl; + } + } else { + for (const auto &entry : for_each_json(options.at(""))) { + const bool subresult = bundle.check( + entry.second, sourcemeta::jsontoolkit::default_schema_walker, + resolver(options), + [&entry](const auto &pointer, const auto &name, const auto &message) { + std::cout << entry.first.string() << "\n"; + std::cout << " "; + sourcemeta::jsontoolkit::stringify(pointer, std::cout); + std::cout << " " << message << " (" << name << ")\n"; + }); + + if (!subresult) { + result = false; + } } } diff --git a/src/utils.cc b/src/utils.cc index c746fed2..11f3aad8 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -62,6 +62,10 @@ auto parse_options(const std::span &arguments, const std::set &flags) -> std::map> { std::map> options; + std::set effective_flags{flags}; + effective_flags.insert("v"); + effective_flags.insert("verbose"); + options.insert({"", {}}); std::optional current_option; for (const auto &argument : arguments) { @@ -72,7 +76,7 @@ auto parse_options(const std::span &arguments, assert(!current_option.value().empty()); options.insert({current_option.value(), {}}); assert(options.contains(current_option.value())); - if (flags.contains(current_option.value())) { + if (effective_flags.contains(current_option.value())) { current_option = std::nullopt; } @@ -83,7 +87,7 @@ auto parse_options(const std::span &arguments, assert(current_option.value().size() == 1); options.insert({current_option.value(), {}}); assert(options.contains(current_option.value())); - if (flags.contains(current_option.value())) { + if (effective_flags.contains(current_option.value())) { current_option = std::nullopt; } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3dee5ede..cc06d67b 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -22,3 +22,4 @@ add_jsonschema_test_unix(test_single_fail) add_jsonschema_test_unix(test_single_unsupported) add_jsonschema_test_unix(lint_pass) add_jsonschema_test_unix(lint_fail) +add_jsonschema_test_unix(lint_fix) diff --git a/test/lint_fix.sh b/test/lint_fix.sh new file mode 100755 index 00000000..5f9e2853 --- /dev/null +++ b/test/lint_fix.sh @@ -0,0 +1,28 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +TMP="$(mktemp -d)" +# shellcheck disable=SC2317 +clean() { rm -rf "$TMP"; } +trap clean EXIT + +cat << 'EOF' > "$TMP/schema.json" +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "type": "string", + "enum": [ "foo" ] +} +EOF + +"$1" lint "$TMP/schema.json" --fix + +cat << 'EOF' > "$TMP/expected.json" +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "const": "foo" +} +EOF + +diff "$TMP/schema.json" "$TMP/expected.json"