Serenity Operating System
at master 133 lines 5.0 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include "AST.h" 10#include "NodeVisitor.h" 11#include <AK/DeprecatedString.h> 12#include <AK/Forward.h> 13#include <AK/StringBuilder.h> 14#include <AK/StringView.h> 15#include <AK/Types.h> 16#include <AK/Vector.h> 17#include <ctype.h> 18 19namespace Shell { 20 21class Formatter final : public AST::NodeVisitor { 22public: 23 Formatter(StringView source, ssize_t cursor = -1, bool parse_as_posix = false) 24 : m_builders({ StringBuilder { round_up_to_power_of_two(source.length(), 16) } }) 25 , m_source(source) 26 , m_cursor(cursor) 27 , m_parse_as_posix(parse_as_posix) 28 { 29 if (m_source.is_empty()) 30 return; 31 32 size_t offset = 0; 33 for (auto ptr = m_source.end() - 1; ptr >= m_source.begin() && isspace(*ptr); --ptr) 34 ++offset; 35 36 m_trivia = m_source.substring_view(m_source.length() - offset, offset); 37 } 38 39 explicit Formatter(const AST::Node& node) 40 : m_builders({ StringBuilder {} }) 41 , m_cursor(-1) 42 , m_root_node(node) 43 { 44 } 45 46 DeprecatedString format(); 47 size_t cursor() const { return m_output_cursor; } 48 49private: 50 virtual void visit(const AST::PathRedirectionNode*) override; 51 virtual void visit(const AST::And*) override; 52 virtual void visit(const AST::ListConcatenate*) override; 53 virtual void visit(const AST::Background*) override; 54 virtual void visit(const AST::BarewordLiteral*) override; 55 virtual void visit(const AST::BraceExpansion*) override; 56 virtual void visit(const AST::CastToCommand*) override; 57 virtual void visit(const AST::CastToList*) override; 58 virtual void visit(const AST::CloseFdRedirection*) override; 59 virtual void visit(const AST::CommandLiteral*) override; 60 virtual void visit(const AST::Comment*) override; 61 virtual void visit(const AST::ContinuationControl*) override; 62 virtual void visit(const AST::DynamicEvaluate*) override; 63 virtual void visit(const AST::DoubleQuotedString*) override; 64 virtual void visit(const AST::Fd2FdRedirection*) override; 65 virtual void visit(const AST::FunctionDeclaration*) override; 66 virtual void visit(const AST::ForLoop*) override; 67 virtual void visit(const AST::Glob*) override; 68 virtual void visit(const AST::Heredoc*) override; 69 virtual void visit(const AST::HistoryEvent*) override; 70 virtual void visit(const AST::Execute*) override; 71 virtual void visit(const AST::IfCond*) override; 72 virtual void visit(const AST::ImmediateExpression*) override; 73 virtual void visit(const AST::Join*) override; 74 virtual void visit(const AST::MatchExpr*) override; 75 virtual void visit(const AST::Or*) override; 76 virtual void visit(const AST::Pipe*) override; 77 virtual void visit(const AST::Range*) override; 78 virtual void visit(const AST::ReadRedirection*) override; 79 virtual void visit(const AST::ReadWriteRedirection*) override; 80 virtual void visit(const AST::Sequence*) override; 81 virtual void visit(const AST::Subshell*) override; 82 virtual void visit(const AST::Slice*) override; 83 virtual void visit(const AST::SimpleVariable*) override; 84 virtual void visit(const AST::SpecialVariable*) override; 85 virtual void visit(const AST::Juxtaposition*) override; 86 virtual void visit(const AST::StringLiteral*) override; 87 virtual void visit(const AST::StringPartCompose*) override; 88 virtual void visit(const AST::SyntaxError*) override; 89 virtual void visit(const AST::Tilde*) override; 90 virtual void visit(const AST::VariableDeclarations*) override; 91 virtual void visit(const AST::WriteAppendRedirection*) override; 92 virtual void visit(const AST::WriteRedirection*) override; 93 94 void test_and_update_output_cursor(const AST::Node*); 95 void visited(const AST::Node*); 96 void will_visit(const AST::Node*); 97 void insert_separator(bool escaped = false); 98 void insert_indent(); 99 100 ALWAYS_INLINE void with_added_indent(int indent, Function<void()>); 101 ALWAYS_INLINE void in_new_block(Function<void()>); 102 ALWAYS_INLINE DeprecatedString in_new_builder(Function<void()>, StringBuilder new_builder = StringBuilder {}); 103 104 StringBuilder& current_builder() { return m_builders.last(); } 105 106 struct Options { 107 size_t max_line_length_hint { 80 }; 108 bool explicit_parentheses { false }; 109 bool explicit_braces { false }; 110 bool in_double_quotes { false }; 111 bool in_heredoc { false }; 112 } m_options; 113 114 size_t m_current_indent { 0 }; 115 116 Vector<StringBuilder> m_builders; 117 118 StringView m_source; 119 size_t m_output_cursor { 0 }; 120 ssize_t m_cursor { -1 }; 121 RefPtr<AST::Node const> m_root_node; 122 AST::Node const* m_hit_node { nullptr }; 123 124 const AST::Node* m_parent_node { nullptr }; 125 const AST::Node* m_last_visited_node { nullptr }; 126 127 StringView m_trivia; 128 Vector<DeprecatedString> m_heredocs_to_append_after_sequence; 129 130 bool m_parse_as_posix { false }; 131}; 132 133}