From 01043ca53aec142003fc3899679e5d14531009c9 Mon Sep 17 00:00:00 2001 From: Dieter Baron Date: Mon, 8 Jan 2024 20:29:02 +0100 Subject: [PATCH] Fix implicit outputs. --- src/Text.cc | 32 ++++++++++++++++++++++++++------ src/Text.h | 7 ++++++- tests/implicit-output.test | 29 +++++++++++++++++++++++++++++ 3 files changed, 61 insertions(+), 7 deletions(-) create mode 100644 tests/implicit-output.test diff --git a/src/Text.cc b/src/Text.cc index b256ea9..ef286ce 100644 --- a/src/Text.cc +++ b/src/Text.cc @@ -31,9 +31,29 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "Text.h" - +#include "Exception.h" #include "File.h" -#include + +// clang-format: off +const std::unordered_map Text::typemap = { + { Tokenizer::TokenType::IMPLICIT_DEPENDENCY, ElementType::PUNCTUATION }, + { Tokenizer::TokenType::ORDER_DEPENDENCY, ElementType::PUNCTUATION }, + { Tokenizer::TokenType::SPACE, ElementType::WHITESPACE }, + { Tokenizer::TokenType::VALIDATION_DEPENDENCY, ElementType::PUNCTUATION }, +}; + +// clang-format: on + +Text::Element::Element(const Tokenizer::Token& token) { + const auto it = typemap.find(token.type); + if (it != typemap.end()) { + type = it->second; + } + else { + type = ElementType::WORD; + } + value = token.string(); +} std::string Text::Element::string() const { if (!is_word() && !is_file()) { @@ -41,7 +61,7 @@ std::string Text::Element::string() const { } else { auto result = std::string{}; - auto index = size_t{0}; + auto index = size_t{ 0 }; while (index < value.size()) { const auto special = value.find_first_of("$ \n", index); @@ -98,7 +118,7 @@ Text::Text(Tokenizer& tokenizer, Tokenizer::TokenType terminator) { } // fallthrough default: - emplace_back((token.is_whitespace() ? ElementType::WHITESPACE : ElementType::WORD), token.string()); + emplace_back(token); break; } } @@ -148,7 +168,7 @@ void Text::collect_words(std::unordered_set& words) const { element.variable->value.collect_words(words); } } - else { + else if (element.is_word() || element.is_build_file()) { words.insert(element.value); } } @@ -157,7 +177,7 @@ void Text::collect_words(std::unordered_set& words) const { std::string Text::string() const { auto result = std::string{}; - for (auto& element: *this) { + for (auto& element : *this) { result += element.string(); } diff --git a/src/Text.h b/src/Text.h index 3897b9f..f7cee22 100644 --- a/src/Text.h +++ b/src/Text.h @@ -55,12 +55,14 @@ class Text { enum class ElementType { BUILD_FILE, SOURCE_FILE, + PUNCTUATION, VARIABLE, WHITESPACE, WORD }; class Element { public: + Element(const Tokenizer::Token& token); Element(ElementType type, std::string value) : type{type}, value{ std::move(value) } {} [[nodiscard]] bool is_build_file() const {return type == ElementType::BUILD_FILE;} @@ -72,7 +74,7 @@ class Text { ElementType type; std::string value; - const Variable *variable = nullptr; + const Variable *variable{}; }; Text() = default; @@ -82,6 +84,7 @@ class Text { void append(const Text& other) {elements.insert(elements.end(), other.elements.begin(), other.elements.end());} void emplace_back(ElementType type, std::string value) { elements.emplace_back(type, std::move(value)); } + void emplace_back(const Element& element) { elements.emplace_back(element); } void print(std::ostream& stream) const; void process(const File& file); @@ -103,6 +106,8 @@ class Text { private: std::vector elements; + + static const std::unordered_map typemap; }; std::ostream& operator<<(std::ostream& stream, const Text& text); diff --git a/tests/implicit-output.test b/tests/implicit-output.test new file mode 100644 index 0000000..d2cba38 --- /dev/null +++ b/tests/implicit-output.test @@ -0,0 +1,29 @@ +arguments .. +file input <> +input +end-of-inline-data +file build.fninja <> +rule a + command = a $in $out + flags = --verbose + +build output | implicit: a input | output +end-of-inline-data +file build/build.ninja {} <> +top_source_directory = .. +source_directory = .. +top_build_directory = . +build_directory = . + +rule a + command = a $in $out + flags = --verbose + +rule fast-ninja + command = fast-ninja $top_source_directory + generator = 1 + +build $build_directory/output | $build_directory/implicit : a $source_directory/input | $build_directory/output + +build ./build.ninja : fast-ninja ../build.fninja +end-of-inline-data