diff options
-rw-r--r-- | Userland/Libraries/LibCodeComprehension/Shell/ShellComprehensionEngine.cpp | 10 | ||||
-rw-r--r-- | Userland/Shell/AST.cpp | 423 | ||||
-rw-r--r-- | Userland/Shell/AST.h | 190 | ||||
-rw-r--r-- | Userland/Shell/Builtin.cpp | 57 | ||||
-rw-r--r-- | Userland/Shell/Formatter.cpp | 4 | ||||
-rw-r--r-- | Userland/Shell/Formatter.h | 1 | ||||
-rw-r--r-- | Userland/Shell/ImmediateFunctions.cpp | 132 | ||||
-rw-r--r-- | Userland/Shell/Parser.cpp | 219 | ||||
-rw-r--r-- | Userland/Shell/Parser.h | 4 | ||||
-rw-r--r-- | Userland/Shell/PosixParser.cpp | 98 | ||||
-rw-r--r-- | Userland/Shell/Shell.cpp | 59 | ||||
-rw-r--r-- | Userland/Shell/main.cpp | 9 |
12 files changed, 625 insertions, 581 deletions
diff --git a/Userland/Libraries/LibCodeComprehension/Shell/ShellComprehensionEngine.cpp b/Userland/Libraries/LibCodeComprehension/Shell/ShellComprehensionEngine.cpp index 504343f001..7b4e20b320 100644 --- a/Userland/Libraries/LibCodeComprehension/Shell/ShellComprehensionEngine.cpp +++ b/Userland/Libraries/LibCodeComprehension/Shell/ShellComprehensionEngine.cpp @@ -78,7 +78,7 @@ Vector<DeprecatedString> const& ShellComprehensionEngine::DocumentData::sourced_ auto& filename = entries[1]; if (filename->would_execute()) return; - auto name_list = const_cast<::Shell::AST::Node*>(filename.ptr())->run(nullptr)->resolve_as_list(nullptr); + auto name_list = const_cast<::Shell::AST::Node*>(filename.ptr())->run(nullptr)->resolve_as_list(nullptr).release_value_but_fixme_should_propagate_errors(); StringBuilder builder; builder.join(' ', name_list); sourced_files.set(builder.to_deprecated_string()); @@ -107,7 +107,7 @@ NonnullRefPtr<::Shell::AST::Node> ShellComprehensionEngine::DocumentData::parse( if (auto node = parser.parse()) return node.release_nonnull(); - return ::Shell::AST::make_ref_counted<::Shell::AST::SyntaxError>(::Shell::AST::Position {}, "Unable to parse file"); + return ::Shell::AST::make_ref_counted<::Shell::AST::SyntaxError>(::Shell::AST::Position {}, String::from_utf8("Unable to parse file"sv).release_value_but_fixme_should_propagate_errors()); } size_t ShellComprehensionEngine::resolve(ShellComprehensionEngine::DocumentData const& document, const GUI::TextPosition& position) @@ -184,7 +184,7 @@ Optional<CodeComprehension::ProjectLocation> ShellComprehensionEngine::find_decl auto& declarations = all_declarations(); for (auto& entry : declarations) { for (auto& declaration : entry.value) { - if (declaration.name == name) + if (declaration.name.view() == name) return declaration.position; } } @@ -209,7 +209,7 @@ void ShellComprehensionEngine::update_declared_symbols(DocumentData const& docum DeprecatedString name; if (literal->is_bareword()) - name = static_ptr_cast<::Shell::AST::BarewordLiteral const>(literal)->text(); + name = static_ptr_cast<::Shell::AST::BarewordLiteral const>(literal)->text().to_deprecated_string(); if (!name.is_empty()) { dbgln("Found variable {}", name); @@ -222,7 +222,7 @@ void ShellComprehensionEngine::update_declared_symbols(DocumentData const& docum void visit(::Shell::AST::FunctionDeclaration const* node) override { dbgln("Found function {}", node->name().name); - declarations.append({ node->name().name, { filename, node->position().start_line.line_number, node->position().start_line.line_column }, CodeComprehension::DeclarationType::Function, {} }); + declarations.append({ node->name().name.to_deprecated_string(), { filename, node->position().start_line.line_number, node->position().start_line.line_column }, CodeComprehension::DeclarationType::Function, {} }); } DeprecatedString const& filename; diff --git a/Userland/Shell/AST.cpp b/Userland/Shell/AST.cpp index 838b5e01f7..a407bb1b6c 100644 --- a/Userland/Shell/AST.cpp +++ b/Userland/Shell/AST.cpp @@ -6,10 +6,10 @@ #include "AST.h" #include "Shell.h" -#include <AK/DeprecatedString.h> #include <AK/MemoryStream.h> #include <AK/ScopeGuard.h> #include <AK/ScopedValueRollback.h> +#include <AK/String.h> #include <AK/StringBuilder.h> #include <AK/URL.h> #include <LibCore/DeprecatedFile.h> @@ -108,7 +108,7 @@ namespace Shell::AST { static inline void print_indented(StringView str, int indent) { - dbgln("{}{}", DeprecatedString::repeated(' ', indent * 2), str); + dbgln("{: >{}}", str, str.length() + indent * 2); } static inline Optional<Position> merge_positions(Optional<Position> const& left, Optional<Position> const& right) @@ -154,7 +154,7 @@ static inline Vector<Command> join_commands(Vector<Command> left, Vector<Command return commands; } -static DeprecatedString resolve_slices(RefPtr<Shell> shell, DeprecatedString&& input_value, NonnullRefPtrVector<Slice> slices) +static String resolve_slices(RefPtr<Shell> shell, String&& input_value, NonnullRefPtrVector<Slice> slices) { if (slices.is_empty()) return move(input_value); @@ -169,13 +169,13 @@ static DeprecatedString resolve_slices(RefPtr<Shell> shell, DeprecatedString&& i return move(input_value); } - auto index_values = value->resolve_as_list(shell); + auto index_values = value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); Vector<size_t> indices; indices.ensure_capacity(index_values.size()); size_t i = 0; for (auto& value : index_values) { - auto maybe_index = value.to_int(); + auto maybe_index = value.bytes_as_string_view().to_int(); if (!maybe_index.has_value()) { shell->raise_error(Shell::ShellError::InvalidSliceContentsError, DeprecatedString::formatted("Invalid value in slice index {}: {} (expected a number)", i, value), slice.position()); return move(input_value); @@ -185,10 +185,10 @@ static DeprecatedString resolve_slices(RefPtr<Shell> shell, DeprecatedString&& i auto index = maybe_index.value(); auto original_index = index; if (index < 0) - index += input_value.length(); + index += input_value.bytes_as_string_view().length(); - if (index < 0 || (size_t)index >= input_value.length()) { - shell->raise_error(Shell::ShellError::InvalidSliceContentsError, DeprecatedString::formatted("Slice index {} (evaluated as {}) out of value bounds [0-{})", index, original_index, input_value.length()), slice.position()); + if (index < 0 || (size_t)index >= input_value.bytes_as_string_view().length()) { + shell->raise_error(Shell::ShellError::InvalidSliceContentsError, DeprecatedString::formatted("Slice index {} (evaluated as {}) out of value bounds [0-{})", index, original_index, input_value.bytes_as_string_view().length()), slice.position()); return move(input_value); } indices.unchecked_append(index); @@ -196,15 +196,15 @@ static DeprecatedString resolve_slices(RefPtr<Shell> shell, DeprecatedString&& i StringBuilder builder { indices.size() }; for (auto& index : indices) - builder.append(input_value[index]); + builder.append(input_value.bytes_as_string_view()[index]); - input_value = builder.to_deprecated_string(); + input_value = builder.to_string().release_value_but_fixme_should_propagate_errors(); } return move(input_value); } -static Vector<DeprecatedString> resolve_slices(RefPtr<Shell> shell, Vector<DeprecatedString>&& values, NonnullRefPtrVector<Slice> slices) +static Vector<String> resolve_slices(RefPtr<Shell> shell, Vector<String>&& values, NonnullRefPtrVector<Slice> slices) { if (slices.is_empty()) return move(values); @@ -219,13 +219,13 @@ static Vector<DeprecatedString> resolve_slices(RefPtr<Shell> shell, Vector<Depre return move(values); } - auto index_values = value->resolve_as_list(shell); + auto index_values = value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); Vector<size_t> indices; indices.ensure_capacity(index_values.size()); size_t i = 0; for (auto& value : index_values) { - auto maybe_index = value.to_int(); + auto maybe_index = value.bytes_as_string_view().to_int(); if (!maybe_index.has_value()) { shell->raise_error(Shell::ShellError::InvalidSliceContentsError, DeprecatedString::formatted("Invalid value in slice index {}: {} (expected a number)", i, value), slice.position()); return move(values); @@ -244,7 +244,7 @@ static Vector<DeprecatedString> resolve_slices(RefPtr<Shell> shell, Vector<Depre indices.unchecked_append(index); } - Vector<DeprecatedString> result; + Vector<String> result; result.ensure_capacity(indices.size()); for (auto& index : indices) result.unchecked_append(values[index]); @@ -276,7 +276,7 @@ bool Node::is_syntax_error() const void Node::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(NonnullRefPtr<Value>)> callback) { - auto value = run(shell)->resolve_without_cast(shell); + auto value = run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return; @@ -286,7 +286,7 @@ void Node::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Nonnul } if (value->is_list_without_resolution()) { - auto list = value->resolve_without_cast(shell); + auto list = value->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); for (auto& element : static_cast<ListValue*>(list.ptr())->values()) { if (callback(element) == IterationDecision::Break) break; @@ -294,7 +294,7 @@ void Node::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Nonnul return; } - auto list = value->resolve_as_list(shell); + auto list = value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); for (auto& element : list) { if (callback(make_ref_counted<StringValue>(move(element))) == IterationDecision::Break) break; @@ -310,13 +310,13 @@ Vector<Command> Node::to_lazy_evaluated_commands(RefPtr<Shell> shell) }; } - return run(shell)->resolve_as_commands(shell); + return run(shell)->resolve_as_commands(shell).release_value_but_fixme_should_propagate_errors(); } void Node::dump(int level) const { print_indented(DeprecatedString::formatted("{} at {}:{} (from {}.{} to {}.{})", - class_name().characters(), + class_name(), m_position.start_offset, m_position.end_offset, m_position.start_line.line_number, @@ -380,7 +380,7 @@ Vector<Line::CompletionSuggestion> Node::complete_for_editor(Shell& shell, size_ if (!program_name_node) return {}; - DeprecatedString program_name; + String program_name; if (program_name_node->is_bareword()) program_name = static_cast<BarewordLiteral const*>(program_name_node.ptr())->text(); else @@ -475,15 +475,17 @@ RefPtr<Value> ListConcatenate::run(RefPtr<Shell> shell) if (shell && shell->has_any_error()) break; if (!result) { - result = make_ref_counted<ListValue>({ element->run(shell)->resolve_without_cast(shell) }); + result = make_ref_counted<ListValue>({ element->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors() }); continue; } - auto element_value = element->run(shell)->resolve_without_cast(shell); + auto element_value = element->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) break; if (result->is_command() || element_value->is_command()) { - auto joined_commands = join_commands(result->resolve_as_commands(shell), element_value->resolve_as_commands(shell)); + auto joined_commands = join_commands( + result->resolve_as_commands(shell).release_value_but_fixme_should_propagate_errors(), + element_value->resolve_as_commands(shell).release_value_but_fixme_should_propagate_errors()); if (joined_commands.size() == 1) { auto& command = joined_commands[0]; @@ -498,7 +500,7 @@ RefPtr<Value> ListConcatenate::run(RefPtr<Shell> shell) if (result->is_list_without_resolution()) { values.extend(static_cast<ListValue*>(result.ptr())->values()); } else { - for (auto& result : result->resolve_as_list(shell)) + for (auto& result : result->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()) values.append(make_ref_counted<StringValue>(result)); } @@ -644,29 +646,29 @@ void BarewordLiteral::highlight_in_editor(Line::Editor& editor, Shell& shell, Hi } if (m_text.starts_with('-')) { - if (m_text == "--") { + if (m_text == "--"sv) { editor.stylize({ m_position.start_offset, m_position.end_offset }, { Line::Style::Foreground(Line::Style::XtermColor::Green) }); return; } - if (m_text == "-") + if (m_text == "-"sv) return; - if (m_text.starts_with("--"sv)) { - auto index = m_text.find('=').value_or(m_text.length() - 1) + 1; + if (m_text.starts_with_bytes("--"sv)) { + auto index = m_text.find_byte_offset('=').value_or(m_text.bytes_as_string_view().length() - 1) + 1; editor.stylize({ m_position.start_offset, m_position.start_offset + index }, { Line::Style::Foreground(Line::Style::XtermColor::Cyan) }); } else { editor.stylize({ m_position.start_offset, m_position.end_offset }, { Line::Style::Foreground(Line::Style::XtermColor::Cyan) }); } } if (Core::DeprecatedFile::exists(m_text)) { - auto realpath = shell.resolve_path(m_text); + auto realpath = shell.resolve_path(m_text.bytes_as_string_view()); auto url = URL::create_with_file_scheme(realpath); url.set_host(shell.hostname); editor.stylize({ m_position.start_offset, m_position.end_offset }, { Line::Style::Hyperlink(url.to_deprecated_string()) }); } } -BarewordLiteral::BarewordLiteral(Position position, DeprecatedString text) +BarewordLiteral::BarewordLiteral(Position position, String text) : Node(move(position)) , m_text(move(text)) { @@ -738,14 +740,14 @@ RefPtr<Value> CastToCommand::run(RefPtr<Shell> shell) if (m_inner->is_command()) return m_inner->run(shell); - auto value = m_inner->run(shell)->resolve_without_cast(shell); + auto value = m_inner->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); if (value->is_command()) return value; - auto argv = value->resolve_as_list(shell); + auto argv = value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); return make_ref_counted<CommandValue>(move(argv), position()); } @@ -773,7 +775,7 @@ Vector<Line::CompletionSuggestion> CastToCommand::complete_for_editor(Shell& she auto corrected_offset = offset - matching_node->position().start_offset; auto* node = static_cast<BarewordLiteral const*>(matching_node.ptr()); - if (corrected_offset > node->text().length()) + if (corrected_offset > node->text().bytes_as_string_view().length()) return {}; return shell.complete_program_name(node->text(), corrected_offset); @@ -806,14 +808,14 @@ RefPtr<Value> CastToList::run(RefPtr<Shell> shell) if (!m_inner) return make_ref_counted<ListValue>({}); - auto inner_value = m_inner->run(shell)->resolve_without_cast(shell); + auto inner_value = m_inner->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); if (inner_value->is_command() || inner_value->is_list()) return inner_value; - auto values = inner_value->resolve_as_list(shell); + auto values = inner_value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); NonnullRefPtrVector<Value> cast_values; for (auto& value : values) cast_values.append(make_ref_counted<StringValue>(value)); @@ -921,7 +923,7 @@ void Comment::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadat editor.stylize({ m_position.start_offset, m_position.end_offset }, { Line::Style::Foreground(150, 150, 150) }); // Light gray } -Comment::Comment(Position position, DeprecatedString text) +Comment::Comment(Position position, String text) : Node(move(position)) , m_text(move(text)) { @@ -962,11 +964,11 @@ void DoubleQuotedString::dump(int level) const RefPtr<Value> DoubleQuotedString::run(RefPtr<Shell> shell) { StringBuilder builder; - auto values = m_inner->run(shell)->resolve_as_list(shell); + auto values = m_inner->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); builder.join(""sv, values); - return make_ref_counted<StringValue>(builder.to_deprecated_string()); + return make_ref_counted<StringValue>(builder.to_string().release_value_but_fixme_should_propagate_errors()); } void DoubleQuotedString::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata) @@ -1005,20 +1007,20 @@ void DynamicEvaluate::dump(int level) const RefPtr<Value> DynamicEvaluate::run(RefPtr<Shell> shell) { - auto result = m_inner->run(shell)->resolve_without_cast(shell); + auto result = m_inner->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); // Dynamic Evaluation behaves differently between strings and lists. // Strings are treated as variables, and Lists are treated as commands. if (result->is_string()) { - auto name_part = result->resolve_as_list(shell); + auto name_part = result->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); VERIFY(name_part.size() == 1); return make_ref_counted<SimpleVariableValue>(name_part[0]); } // If it's anything else, we're just gonna cast it to a list. - auto list = result->resolve_as_list(shell); + auto list = result->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); return make_ref_counted<CommandValue>(move(list), position()); } @@ -1094,9 +1096,9 @@ RefPtr<Value> FunctionDeclaration::run(RefPtr<Shell> shell) { Vector<DeprecatedString> args; for (auto& arg : m_arguments) - args.append(arg.name); + args.append(arg.name.to_deprecated_string()); - shell->define_function(m_name.name, move(args), m_block); + shell->define_function(m_name.name.to_deprecated_string(), move(args), m_block); return make_ref_counted<ListValue>({}); } @@ -1136,12 +1138,12 @@ Vector<Line::CompletionSuggestion> FunctionDeclaration::complete_for_editor(Shel auto corrected_offset = offset - matching_node->position().start_offset - 1; // Skip the first '$' auto* node = static_cast<SimpleVariable const*>(matching_node.ptr()); - auto name = node->name().substring_view(0, corrected_offset); + auto name = node->name().bytes_as_string_view().substring_view(0, corrected_offset); Vector<Line::CompletionSuggestion> results; for (auto& arg : m_arguments) { - if (arg.name.starts_with(name)) - results.append(arg.name); + if (arg.name.starts_with_bytes(name)) + results.append(arg.name.to_deprecated_string()); } results.extend(matching_node->complete_for_editor(shell, offset, hit_test_result)); @@ -1219,7 +1221,7 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell) }; if (m_iterated_expression) { - auto variable_name = m_variable.has_value() ? m_variable->name : "it"; + auto variable_name = m_variable.has_value() ? m_variable->name : String::from_utf8_short_string("it"sv); Optional<StringView> index_name = m_index_variable.has_value() ? Optional<StringView>(m_index_variable->name) : Optional<StringView>(); size_t i = 0; m_iterated_expression->for_each_entry(shell, [&](auto value) { @@ -1238,10 +1240,10 @@ RefPtr<Value> ForLoop::run(RefPtr<Shell> shell) { auto frame = shell->push_frame(DeprecatedString::formatted("for ({})", this)); - shell->set_local_variable(variable_name, value, true); + shell->set_local_variable(variable_name.bytes_as_string_view(), value, true); if (index_name.has_value()) - shell->set_local_variable(index_name.value(), make_ref_counted<AST::StringValue>(DeprecatedString::number(i)), true); + shell->set_local_variable(index_name.value(), make_ref_counted<AST::StringValue>(String::number(i).release_value_but_fixme_should_propagate_errors()), true); ++i; @@ -1349,7 +1351,7 @@ void Glob::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata m editor.stylize({ m_position.start_offset, m_position.end_offset }, move(style)); } -Glob::Glob(Position position, DeprecatedString text) +Glob::Glob(Position position, String text) : Node(move(position)) , m_text(move(text)) { @@ -1396,19 +1398,19 @@ RefPtr<Value> Heredoc::run(RefPtr<Shell> shell) if (!value) return value; - auto list = value->resolve_as_list(shell); + auto list = value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); // The list better have one entry, otherwise we've put the wrong kind of node inside this heredoc VERIFY(list.size() == 1); - auto lines = list.first().split_view('\n'); + auto lines = list.first().bytes_as_string_view().split_view('\n'); // Now just trim each line and put them back in a string - StringBuilder builder { list.first().length() }; + StringBuilder builder { list.first().bytes_as_string_view().length() }; for (auto& line : lines) { builder.append(line.trim_whitespace(TrimMode::Left)); builder.append('\n'); } - return make_ref_counted<StringValue>(builder.to_deprecated_string()); + return make_ref_counted<StringValue>(builder.to_string().release_value_but_fixme_should_propagate_errors()); }(); if (evaluates_to_string()) @@ -1434,11 +1436,12 @@ RefPtr<Value> Heredoc::run(RefPtr<Shell> shell) return nullptr; } - auto text = value->resolve_as_string(shell); + auto text = value->resolve_as_string(shell).release_value_but_fixme_should_propagate_errors(); + auto bytes = text.bytes(); - auto written = fwrite(text.characters(), 1, text.length(), file); + auto written = fwrite(bytes.data(), 1, bytes.size(), file); fflush(file); - if (written != text.length()) { + if (written != bytes.size()) { if (shell) shell->raise_error(Shell::ShellError::WriteFailure, "heredoc"sv, position()); } @@ -1472,7 +1475,7 @@ HitTestResult Heredoc::hit_test_position(size_t offset) const return m_contents->hit_test_position(offset); } -Heredoc::Heredoc(Position position, DeprecatedString end, bool allow_interpolation, bool deindent, Optional<int> target_fd) +Heredoc::Heredoc(Position position, String end, bool allow_interpolation, bool deindent, Optional<int> target_fd) : Node(move(position)) , m_end(move(end)) , m_allows_interpolation(allow_interpolation) @@ -1653,7 +1656,7 @@ void Execute::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Non if (m_command->would_execute()) return m_command->for_each_entry(shell, move(callback)); - auto unexpanded_commands = m_command->run(shell)->resolve_as_commands(shell); + auto unexpanded_commands = m_command->run(shell)->resolve_as_commands(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return; @@ -1708,7 +1711,7 @@ void Execute::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Non stream.discard(ifs.length()).release_value_but_fixme_should_propagate_errors(); if (shell->options.inline_exec_keep_empty_segments) - if (callback(make_ref_counted<StringValue>("")) == IterationDecision::Break) { + if (callback(make_ref_counted<StringValue>(String {})) == IterationDecision::Break) { loop.quit(Break); notifier->set_enabled(false); return Break; @@ -1723,8 +1726,8 @@ void Execute::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Non auto entry = entry_result.release_value(); stream.read_entire_buffer(entry).release_value_but_fixme_should_propagate_errors(); - auto str = StringView(entry.data(), entry.size() - ifs.length()); - if (callback(make_ref_counted<StringValue>(str)) == IterationDecision::Break) { + auto str = String::from_utf8(StringView(entry.data(), entry.size() - ifs.length())).release_value_but_fixme_should_propagate_errors(); + if (callback(make_ref_counted<StringValue>(move(str))) == IterationDecision::Break) { loop.quit(Break); notifier->set_enabled(false); return Break; @@ -1812,7 +1815,7 @@ void Execute::for_each_entry(RefPtr<Shell> shell, Function<IterationDecision(Non } auto entry = entry_result.release_value(); stream.read_entire_buffer(entry).release_value_but_fixme_should_propagate_errors(); - callback(make_ref_counted<StringValue>(DeprecatedString::copy(entry))); + callback(make_ref_counted<StringValue>(String::from_utf8(entry).release_value_but_fixme_should_propagate_errors())); } } @@ -1872,7 +1875,7 @@ Vector<Line::CompletionSuggestion> Execute::complete_for_editor(Shell& shell, si auto corrected_offset = offset - matching_node->position().start_offset; auto* node = static_cast<BarewordLiteral const*>(matching_node.ptr()); - if (corrected_offset > node->text().length()) + if (corrected_offset > node->text().bytes_as_string_view().length()) return {}; return shell.complete_program_name(node->text(), corrected_offset); @@ -1910,7 +1913,7 @@ void IfCond::dump(int level) const RefPtr<Value> IfCond::run(RefPtr<Shell> shell) { - auto cond = m_condition->run(shell)->resolve_without_cast(shell); + auto cond = m_condition->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); @@ -2051,7 +2054,7 @@ Vector<Line::CompletionSuggestion> ImmediateExpression::complete_for_editor(Shel auto corrected_offset = offset - m_function.position.start_offset; - if (corrected_offset > m_function.name.length()) + if (corrected_offset > m_function.name.bytes_as_string_view().length()) return {}; return shell.complete_immediate_function_name(m_function.name, corrected_offset); @@ -2160,9 +2163,9 @@ Join::~Join() void MatchExpr::dump(int level) const { Node::dump(level); - print_indented(DeprecatedString::formatted("(expression: {})", m_expr_name.characters()), level + 1); + print_indented(DeprecatedString::formatted("(expression: {})", m_expr_name), level + 1); m_matched_expr->dump(level + 2); - print_indented(DeprecatedString::formatted("(named: {})", m_expr_name.characters()), level + 1); + print_indented(DeprecatedString::formatted("(named: {})", m_expr_name), level + 1); print_indented("(entries)"sv, level + 1); for (auto& entry : m_entries) { StringBuilder builder; @@ -2201,11 +2204,11 @@ void MatchExpr::dump(int level) const RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell) { - auto value = m_matched_expr->run(shell)->resolve_without_cast(shell); + auto value = m_matched_expr->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); - auto list = value->resolve_as_list(shell); + auto list = value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); auto list_matches = [&](auto&& pattern, auto& spans) { if constexpr (IsSame<RemoveCVReference<decltype(pattern)>, Regex<ECMA262>>) { @@ -2219,7 +2222,7 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell) spans.ensure_capacity(match.n_capture_groups); for (size_t i = 0; i < match.n_capture_groups; ++i) { auto& capture = match.capture_group_matches[0][i]; - spans.append(capture.view.to_deprecated_string()); + spans.append(capture.view.to_string().release_value_but_fixme_should_propagate_errors()); } return true; } else { @@ -2228,10 +2231,10 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell) for (size_t i = 0; i < pattern.size(); ++i) { Vector<AK::MaskSpan> mask_spans; - if (!list[i].matches(pattern[i], mask_spans)) + if (!list[i].bytes_as_string_view().matches(pattern[i], mask_spans)) return false; for (auto& span : mask_spans) - spans.append(list[i].substring(span.start, span.length)); + spans.append(list[i].substring_from_byte_offset(span.start, span.length).release_value_but_fixme_should_propagate_errors()); } return true; @@ -2242,7 +2245,7 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell) if constexpr (IsSame<RemoveCVReference<decltype(option)>, Regex<ECMA262>>) { return option; } else { - Vector<DeprecatedString> pattern; + Vector<String> pattern; if (option.is_glob()) { pattern.append(static_cast<const Glob*>(&option)->text()); } else if (option.is_bareword()) { @@ -2253,8 +2256,8 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell) return pattern; option.for_each_entry(shell, [&](auto&& value) { - pattern.extend(value->resolve_as_list(nullptr)); // Note: 'nullptr' incurs special behavior, - // asking the node for a 'raw' value. + pattern.extend(value->resolve_as_list(nullptr).release_value_but_fixme_should_propagate_errors()); // Note: 'nullptr' incurs special behavior, + // asking the node for a 'raw' value. return IterationDecision::Continue; }); } @@ -2265,19 +2268,19 @@ RefPtr<Value> MatchExpr::run(RefPtr<Shell> shell) auto frame = shell->push_frame(DeprecatedString::formatted("match ({})", this)); if (!m_expr_name.is_empty()) - shell->set_local_variable(m_expr_name, value, true); + shell->set_local_variable(m_expr_name.to_deprecated_string(), value, true); for (auto& entry : m_entries) { auto result = entry.options.visit([&](auto& options) -> Variant<IterationDecision, RefPtr<Value>> { for (auto& option : options) { - Vector<DeprecatedString> spans; + Vector<String> spans; if (list_matches(resolve_pattern(option), spans)) { if (entry.body) { if (entry.match_names.has_value()) { size_t i = 0; for (auto& name : entry.match_names.value()) { if (spans.size() > i) - shell->set_local_variable(name, make_ref_counted<AST::StringValue>(spans[i]), true); + shell->set_local_variable(name.to_deprecated_string(), make_ref_counted<AST::StringValue>(spans[i]), true); ++i; } } @@ -2346,7 +2349,7 @@ HitTestResult MatchExpr::hit_test_position(size_t offset) const return {}; } -MatchExpr::MatchExpr(Position position, NonnullRefPtr<Node> expr, DeprecatedString name, Optional<Position> as_position, Vector<MatchEntry> entries) +MatchExpr::MatchExpr(Position position, NonnullRefPtr<Node> expr, String name, Optional<Position> as_position, Vector<MatchEntry> entries) : Node(move(position)) , m_matched_expr(move(expr)) , m_expr_name(move(name)) @@ -2537,14 +2540,14 @@ void PathRedirectionNode::highlight_in_editor(Line::Editor& editor, Shell& shell metadata.is_first_in_list = false; m_path->highlight_in_editor(editor, shell, metadata); if (m_path->is_bareword()) { - auto path_text = m_path->run(nullptr)->resolve_as_list(nullptr); + auto path_text = m_path->run(nullptr)->resolve_as_list(nullptr).release_value_but_fixme_should_propagate_errors(); VERIFY(path_text.size() == 1); // Apply a URL to the path. auto& position = m_path->position(); auto& path = path_text[0]; if (!path.starts_with('/')) - path = DeprecatedString::formatted("{}/{}", shell.cwd, path); - auto url = URL::create_with_file_scheme(path); + path = String::formatted("{}/{}", shell.cwd, path).release_value_but_fixme_should_propagate_errors(); + auto url = URL::create_with_file_scheme(path.to_deprecated_string()); url.set_host(shell.hostname); editor.stylize({ position.start_offset, position.end_offset }, { Line::Style::Hyperlink(url.to_deprecated_string()) }); } @@ -2567,7 +2570,7 @@ Vector<Line::CompletionSuggestion> PathRedirectionNode::complete_for_editor(Shel auto corrected_offset = offset - matching_node->position().start_offset; auto* node = static_cast<BarewordLiteral const*>(matching_node.ptr()); - if (corrected_offset > node->text().length()) + if (corrected_offset > node->text().bytes_as_string_view().length()) return {}; return shell.complete_path(""sv, node->text(), corrected_offset, Shell::ExecutableOnly::No, nullptr, nullptr); @@ -2592,8 +2595,8 @@ RefPtr<Value> Range::run(RefPtr<Shell> shell) NonnullRefPtrVector<Value> values; if (start->is_string() && end->is_string()) { - auto start_str = start->resolve_as_list(shell)[0]; - auto end_str = end->resolve_as_list(shell)[0]; + auto start_str = start->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()[0]; + auto end_str = end->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()[0]; Utf8View start_view { start_str }, end_view { end_str }; if (start_view.validate() && end_view.validate()) { @@ -2606,24 +2609,24 @@ RefPtr<Value> Range::run(RefPtr<Shell> shell) for (u32 code_point = start_code_point; code_point != end_code_point; code_point += step) { builder.clear(); builder.append_code_point(code_point); - values.append(make_ref_counted<StringValue>(builder.to_deprecated_string())); + values.append(make_ref_counted<StringValue>(builder.to_string().release_value_but_fixme_should_propagate_errors())); } // Append the ending code point too, most shells treat this as inclusive. builder.clear(); builder.append_code_point(end_code_point); - values.append(make_ref_counted<StringValue>(builder.to_deprecated_string())); + values.append(make_ref_counted<StringValue>(builder.to_string().release_value_but_fixme_should_propagate_errors())); } else { // Could be two numbers? - auto start_int = start_str.to_int(); - auto end_int = end_str.to_int(); + auto start_int = start_str.bytes_as_string_view().to_int(); + auto end_int = end_str.bytes_as_string_view().to_int(); if (start_int.has_value() && end_int.has_value()) { auto start = start_int.value(); auto end = end_int.value(); auto step = start > end ? -1 : 1; for (int value = start; value != end; value += step) - values.append(make_ref_counted<StringValue>(DeprecatedString::number(value))); + values.append(make_ref_counted<StringValue>(String::number(value).release_value_but_fixme_should_propagate_errors())); // Append the range end too, most shells treat this as inclusive. - values.append(make_ref_counted<StringValue>(DeprecatedString::number(end))); + values.append(make_ref_counted<StringValue>(String::number(end).release_value_but_fixme_should_propagate_errors())); } else { goto yield_start_end; } @@ -2708,14 +2711,14 @@ void ReadRedirection::dump(int level) const RefPtr<Value> ReadRedirection::run(RefPtr<Shell> shell) { Command command; - auto path_segments = m_path->run(shell)->resolve_as_list(shell); + auto path_segments = m_path->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); StringBuilder builder; builder.join(' ', path_segments); - command.redirections.append(PathRedirection::create(builder.to_deprecated_string(), m_fd, PathRedirection::Read)); + command.redirections.append(PathRedirection::create(builder.to_string().release_value_but_fixme_should_propagate_errors(), m_fd, PathRedirection::Read)); return make_ref_counted<CommandValue>(move(command)); } @@ -2738,14 +2741,14 @@ void ReadWriteRedirection::dump(int level) const RefPtr<Value> ReadWriteRedirection::run(RefPtr<Shell> shell) { Command command; - auto path_segments = m_path->run(shell)->resolve_as_list(shell); + auto path_segments = m_path->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); StringBuilder builder; builder.join(' ', path_segments); - command.redirections.append(PathRedirection::create(builder.to_deprecated_string(), m_fd, PathRedirection::ReadWrite)); + command.redirections.append(PathRedirection::create(builder.to_string().release_value_but_fixme_should_propagate_errors(), m_fd, PathRedirection::ReadWrite)); return make_ref_counted<CommandValue>(move(command)); } @@ -2933,7 +2936,7 @@ RefPtr<Value> SimpleVariable::run(RefPtr<Shell>) { NonnullRefPtr<Value> value = make_ref_counted<SimpleVariableValue>(m_name); if (m_slice) - value = value->with_slices(*m_slice); + value = value->with_slices(*m_slice).release_value_but_fixme_should_propagate_errors(); return value; } @@ -2969,13 +2972,13 @@ Vector<Line::CompletionSuggestion> SimpleVariable::complete_for_editor(Shell& sh auto corrected_offset = offset - matching_node->position().start_offset - 1; - if (corrected_offset > m_name.length() + 1) + if (corrected_offset > m_name.bytes_as_string_view().length() + 1) return {}; return shell.complete_variable(m_name, corrected_offset); } -SimpleVariable::SimpleVariable(Position position, DeprecatedString name) +SimpleVariable::SimpleVariable(Position position, String name) : VariableNode(move(position)) , m_name(move(name)) { @@ -2989,7 +2992,7 @@ void SpecialVariable::dump(int level) const { Node::dump(level); print_indented("(Name)"sv, level + 1); - print_indented(DeprecatedString { &m_name, 1 }, level + 1); + print_indented(StringView { &m_name, 1 }, level + 1); print_indented("(Slice)"sv, level + 1); if (m_slice) m_slice->dump(level + 2); @@ -3001,7 +3004,7 @@ RefPtr<Value> SpecialVariable::run(RefPtr<Shell>) { NonnullRefPtr<Value> value = make_ref_counted<SpecialVariableValue>(m_name); if (m_slice) - value = value->with_slices(*m_slice); + value = value->with_slices(*m_slice).release_value_but_fixme_should_propagate_errors(); return value; } @@ -3044,19 +3047,19 @@ void Juxtaposition::dump(int level) const RefPtr<Value> Juxtaposition::run(RefPtr<Shell> shell) { - auto left_value = m_left->run(shell)->resolve_without_cast(shell); + auto left_value = m_left->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); - auto right_value = m_right->run(shell)->resolve_without_cast(shell); + auto right_value = m_right->run(shell)->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); - auto left = left_value->resolve_as_list(shell); - auto right = right_value->resolve_as_list(shell); + auto left = left_value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); + auto right = right_value->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (m_mode == Mode::StringExpand) { - Vector<DeprecatedString> result; + Vector<String> result; result.ensure_capacity(left.size() + right.size()); for (auto& left_item : left) @@ -3064,7 +3067,7 @@ RefPtr<Value> Juxtaposition::run(RefPtr<Shell> shell) if (!result.is_empty() && !right.is_empty()) { auto& last = result.last(); - last = DeprecatedString::formatted("{}{}", last, right.first()); + last = String::formatted("{}{}", last, right.first()).release_value_but_fixme_should_propagate_errors(); right.take_first(); } for (auto& right_item : right) @@ -3082,14 +3085,14 @@ RefPtr<Value> Juxtaposition::run(RefPtr<Shell> shell) builder.append(left[0]); builder.append(right[0]); - return make_ref_counted<StringValue>(builder.to_deprecated_string()); + return make_ref_counted<StringValue>(builder.to_string().release_value_but_fixme_should_propagate_errors()); } // Otherwise, treat them as lists and create a list product (or just append). if (left.is_empty() || right.is_empty()) return make_ref_counted<ListValue>({}); - Vector<DeprecatedString> result; + Vector<String> result; result.ensure_capacity(left.size() * right.size()); StringBuilder builder; @@ -3097,7 +3100,7 @@ RefPtr<Value> Juxtaposition::run(RefPtr<Shell> shell) for (auto& right_element : right) { builder.append(left_element); builder.append(right_element); - result.append(builder.to_deprecated_string()); + result.append(builder.to_string().release_value_but_fixme_should_propagate_errors()); builder.clear(); } } @@ -3113,8 +3116,8 @@ void Juxtaposition::highlight_in_editor(Line::Editor& editor, Shell& shell, High // since that resolution is a pure operation, we can just go ahead // and do it to get the value :) if (m_right->is_bareword() && m_left->is_tilde()) { - auto tilde_value = m_left->run(shell)->resolve_as_list(shell)[0]; - auto bareword_value = m_right->run(shell)->resolve_as_list(shell)[0]; + auto tilde_value = m_left->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()[0]; + auto bareword_value = m_right->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()[0]; StringBuilder path_builder; path_builder.append(tilde_value); @@ -3143,14 +3146,14 @@ Vector<Line::CompletionSuggestion> Juxtaposition::complete_for_editor(Shell& she // '~/foo/bar' is special, we have to actually resolve the tilde // then complete the bareword with that path prefix. - auto left_values = m_left->run(shell)->resolve_as_list(shell); + auto left_values = m_left->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (left_values.is_empty()) return m_right->complete_for_editor(shell, offset, hit_test_result); auto& left_value = left_values.first(); - auto right_values = m_right->run(shell)->resolve_as_list(shell); + auto right_values = m_right->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); StringView right_value {}; auto corrected_offset = offset - matching_node->position().start_offset; @@ -3221,7 +3224,7 @@ void StringLiteral::highlight_in_editor(Line::Editor& editor, Shell&, HighlightM editor.stylize({ m_position.start_offset, m_position.end_offset }, move(style)); } -StringLiteral::StringLiteral(Position position, DeprecatedString text, EnclosureType enclosure_type) +StringLiteral::StringLiteral(Position position, String text, EnclosureType enclosure_type) : Node(move(position)) , m_text(move(text)) , m_enclosure_type(enclosure_type) @@ -3241,11 +3244,11 @@ void StringPartCompose::dump(int level) const RefPtr<Value> StringPartCompose::run(RefPtr<Shell> shell) { - auto left = m_left->run(shell)->resolve_as_list(shell); + auto left = m_left->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); - auto right = m_right->run(shell)->resolve_as_list(shell); + auto right = m_right->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); @@ -3253,7 +3256,7 @@ RefPtr<Value> StringPartCompose::run(RefPtr<Shell> shell) builder.join(' ', left); builder.join(' ', right); - return make_ref_counted<StringValue>(builder.to_deprecated_string()); + return make_ref_counted<StringValue>(builder.to_string().release_value_but_fixme_should_propagate_errors()); } void StringPartCompose::highlight_in_editor(Line::Editor& editor, Shell& shell, HighlightMetadata metadata) @@ -3296,8 +3299,8 @@ void SyntaxError::dump(int level) const RefPtr<Value> SyntaxError::run(RefPtr<Shell> shell) { - shell->raise_error(Shell::ShellError::EvaluatedSyntaxError, m_syntax_error_text, position()); - return make_ref_counted<StringValue>(""); + shell->raise_error(Shell::ShellError::EvaluatedSyntaxError, m_syntax_error_text.to_deprecated_string(), position()); + return make_ref_counted<StringValue>(String {}); } void SyntaxError::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMetadata) @@ -3305,7 +3308,7 @@ void SyntaxError::highlight_in_editor(Line::Editor& editor, Shell&, HighlightMet editor.stylize({ m_position.start_offset, m_position.end_offset }, { Line::Style::Foreground(Line::Style::XtermColor::Red), Line::Style::Bold }); } -SyntaxError::SyntaxError(Position position, DeprecatedString error, bool is_continuable) +SyntaxError::SyntaxError(Position position, String error, bool is_continuable) : Node(move(position)) , m_syntax_error_text(move(error)) , m_is_continuable(is_continuable) @@ -3375,21 +3378,21 @@ Vector<Line::CompletionSuggestion> Tilde::complete_for_editor(Shell& shell, size auto corrected_offset = offset - matching_node->position().start_offset - 1; - if (corrected_offset > m_username.length() + 1) + if (corrected_offset > m_username.bytes_as_string_view().length() + 1) return {}; return shell.complete_user(m_username, corrected_offset); } -DeprecatedString Tilde::text() const +String Tilde::text() const { StringBuilder builder; builder.append('~'); builder.append(m_username); - return builder.to_deprecated_string(); + return builder.to_string().release_value_but_fixme_should_propagate_errors(); } -Tilde::Tilde(Position position, DeprecatedString username) +Tilde::Tilde(Position position, String username) : Node(move(position)) , m_username(move(username)) { @@ -3409,14 +3412,14 @@ void WriteAppendRedirection::dump(int level) const RefPtr<Value> WriteAppendRedirection::run(RefPtr<Shell> shell) { Command command; - auto path_segments = m_path->run(shell)->resolve_as_list(shell); + auto path_segments = m_path->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); StringBuilder builder; builder.join(' ', path_segments); - command.redirections.append(PathRedirection::create(builder.to_deprecated_string(), m_fd, PathRedirection::WriteAppend)); + command.redirections.append(PathRedirection::create(builder.to_string().release_value_but_fixme_should_propagate_errors(), m_fd, PathRedirection::WriteAppend)); return make_ref_counted<CommandValue>(move(command)); } @@ -3439,14 +3442,14 @@ void WriteRedirection::dump(int level) const RefPtr<Value> WriteRedirection::run(RefPtr<Shell> shell) { Command command; - auto path_segments = m_path->run(shell)->resolve_as_list(shell); + auto path_segments = m_path->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) return make_ref_counted<ListValue>({}); StringBuilder builder; builder.join(' ', path_segments); - command.redirections.append(PathRedirection::create(builder.to_deprecated_string(), m_fd, PathRedirection::Write)); + command.redirections.append(PathRedirection::create(builder.to_string().release_value_but_fixme_should_propagate_errors(), m_fd, PathRedirection::Write)); return make_ref_counted<CommandValue>(move(command)); } @@ -3472,7 +3475,7 @@ void VariableDeclarations::dump(int level) const RefPtr<Value> VariableDeclarations::run(RefPtr<Shell> shell) { for (auto& var : m_variables) { - auto name_value = var.name->run(shell)->resolve_as_list(shell); + auto name_value = var.name->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors(); if (shell && shell->has_any_error()) break; @@ -3481,9 +3484,9 @@ RefPtr<Value> VariableDeclarations::run(RefPtr<Shell> shell) auto value = var.value->run(shell); if (shell && shell->has_any_error()) break; - value = value->resolve_without_cast(shell); + value = value->resolve_without_cast(shell).release_value_but_fixme_should_propagate_errors(); - shell->set_local_variable(name, value.release_nonnull()); + shell->set_local_variable(name.to_deprecated_string(), value.release_nonnull()); } return make_ref_counted<ListValue>({}); @@ -3535,21 +3538,21 @@ Value::~Value() { } -DeprecatedString Value::resolve_as_string(RefPtr<Shell> shell) +ErrorOr<String> Value::resolve_as_string(RefPtr<Shell> shell) { if (shell) shell->raise_error(Shell::ShellError::EvaluatedSyntaxError, "Conversion to string not allowed"); - return {}; + return String {}; } -Vector<AST::Command> Value::resolve_as_commands(RefPtr<Shell> shell) +ErrorOr<Vector<AST::Command>> Value::resolve_as_commands(RefPtr<Shell> shell) { Command command; - command.argv = resolve_as_list(shell); - return { command }; + command.argv = TRY(resolve_as_list(shell)); + return Vector { move(command) }; } -ListValue::ListValue(Vector<DeprecatedString> values) +ListValue::ListValue(Vector<String> values) { if (values.is_empty()) return; @@ -3558,16 +3561,16 @@ ListValue::ListValue(Vector<DeprecatedString> values) m_contained_values.append(adopt_ref(*new StringValue(move(str)))); } -NonnullRefPtr<Value> Value::with_slices(NonnullRefPtr<Slice> slice) const& +ErrorOr<NonnullRefPtr<Value>> Value::with_slices(NonnullRefPtr<Slice> slice) const& { - auto value = clone(); + auto value = TRY(clone()); value->m_slices.append(move(slice)); return value; } -NonnullRefPtr<Value> Value::with_slices(NonnullRefPtrVector<Slice> slices) const& +ErrorOr<NonnullRefPtr<Value>> Value::with_slices(NonnullRefPtrVector<Slice> slices) const& { - auto value = clone(); + auto value = TRY(clone()); value->m_slices.extend(move(slices)); return value; } @@ -3576,24 +3579,24 @@ ListValue::~ListValue() { } -Vector<DeprecatedString> ListValue::resolve_as_list(RefPtr<Shell> shell) +ErrorOr<Vector<String>> ListValue::resolve_as_list(RefPtr<Shell> shell) { - Vector<DeprecatedString> values; + Vector<String> values; for (auto& value : m_contained_values) - values.extend(value.resolve_as_list(shell)); + values.extend(TRY(value.resolve_as_list(shell))); return resolve_slices(shell, move(values), m_slices); } -NonnullRefPtr<Value> ListValue::resolve_without_cast(RefPtr<Shell> shell) +ErrorOr<NonnullRefPtr<Value>> ListValue::resolve_without_cast(RefPtr<Shell> shell) { NonnullRefPtrVector<Value> values; for (auto& value : m_contained_values) - values.append(value.resolve_without_cast(shell)); + values.append(TRY(value.resolve_without_cast(shell))); NonnullRefPtr<Value> value = make_ref_counted<ListValue>(move(values)); if (!m_slices.is_empty()) - value = value->with_slices(m_slices); + value = TRY(value->with_slices(m_slices)); return value; } @@ -3605,25 +3608,25 @@ CommandSequenceValue::~CommandSequenceValue() { } -Vector<DeprecatedString> CommandSequenceValue::resolve_as_list(RefPtr<Shell> shell) +ErrorOr<Vector<String>> CommandSequenceValue::resolve_as_list(RefPtr<Shell> shell) { shell->raise_error(Shell::ShellError::EvaluatedSyntaxError, "Unexpected cast of a command sequence to a list"); - return {}; + return Vector<String> {}; } -Vector<Command> CommandSequenceValue::resolve_as_commands(RefPtr<Shell>) +ErrorOr<Vector<Command>> CommandSequenceValue::resolve_as_commands(RefPtr<Shell>) { return m_contained_values; } -Vector<DeprecatedString> CommandValue::resolve_as_list(RefPtr<Shell>) +ErrorOr<Vector<String>> CommandValue::resolve_as_list(RefPtr<Shell>) { return m_command.argv; } -Vector<Command> CommandValue::resolve_as_commands(RefPtr<Shell>) +ErrorOr<Vector<Command>> CommandValue::resolve_as_commands(RefPtr<Shell>) { - return { m_command }; + return Vector { m_command }; } JobValue::~JobValue() @@ -3634,31 +3637,31 @@ StringValue::~StringValue() { } -DeprecatedString StringValue::resolve_as_string(RefPtr<Shell> shell) +ErrorOr<String> StringValue::resolve_as_string(RefPtr<Shell> shell) { - if (m_split.is_null()) + if (m_split.is_empty()) return m_string; return Value::resolve_as_string(shell); } -Vector<DeprecatedString> StringValue::resolve_as_list(RefPtr<Shell> shell) +ErrorOr<Vector<String>> StringValue::resolve_as_list(RefPtr<Shell> shell) { if (is_list()) { auto parts = StringView(m_string).split_view(m_split, m_keep_empty ? SplitBehavior::KeepEmpty : SplitBehavior::Nothing); - Vector<DeprecatedString> result; + Vector<String> result; result.ensure_capacity(parts.size()); for (auto& part : parts) - result.append(part); + result.append(TRY(String::from_utf8(part))); return resolve_slices(shell, move(result), m_slices); } - return { resolve_slices(shell, DeprecatedString { m_string }, m_slices) }; + return Vector<String> { resolve_slices(shell, Vector { m_string }, m_slices) }; } -NonnullRefPtr<Value> StringValue::resolve_without_cast(RefPtr<Shell> shell) +ErrorOr<NonnullRefPtr<Value>> StringValue::resolve_without_cast(RefPtr<Shell> shell) { if (is_list()) - return make_ref_counted<AST::ListValue>(resolve_as_list(shell)); // No need to reapply the slices. + return try_make_ref_counted<AST::ListValue>(TRY(resolve_as_list(shell))); // No need to reapply the slices. return *this; } @@ -3666,49 +3669,59 @@ NonnullRefPtr<Value> StringValue::resolve_without_cast(RefPtr<Shell> shell) GlobValue::~GlobValue() { } -Vector<DeprecatedString> GlobValue::resolve_as_list(RefPtr<Shell> shell) + +ErrorOr<Vector<String>> GlobValue::resolve_as_list(RefPtr<Shell> shell) { if (!shell) - return { resolve_slices(shell, DeprecatedString { m_glob }, m_slices) }; + return resolve_slices(shell, Vector { m_glob }, m_slices); auto results = shell->expand_globs(m_glob, shell->cwd); if (results.is_empty()) shell->raise_error(Shell::ShellError::InvalidGlobError, "Glob did not match anything!", m_generation_position); - return resolve_slices(shell, move(results), m_slices); + + Vector<String> strings; + TRY(strings.try_ensure_capacity(results.size())); + for (auto& entry : results) { + TRY(strings.try_append(TRY(String::from_utf8(entry)))); + } + + return resolve_slices(shell, move(strings), m_slices); } SimpleVariableValue::~SimpleVariableValue() { } -DeprecatedString SimpleVariableValue::resolve_as_string(RefPtr<Shell> shell) +ErrorOr<String> SimpleVariableValue::resolve_as_string(RefPtr<Shell> shell) { if (!shell) - return resolve_slices(shell, DeprecatedString {}, m_slices); + return resolve_slices(shell, String {}, m_slices); - if (auto value = resolve_without_cast(shell); value != this) + if (auto value = TRY(resolve_without_cast(shell)); value != this) return value->resolve_as_string(shell); - char* env_value = getenv(m_name.characters()); - return resolve_slices(shell, env_value, m_slices); + auto name = m_name.to_deprecated_string(); + char* env_value = getenv(name.characters()); + return resolve_slices(shell, TRY(String::from_utf8(StringView { env_value, strlen(env_value) })), m_slices); } -Vector<DeprecatedString> SimpleVariableValue::resolve_as_list(RefPtr<Shell> shell) +ErrorOr<Vector<String>> SimpleVariableValue::resolve_as_list(RefPtr<Shell> shell) { if (!shell) - return resolve_slices(shell, Vector<DeprecatedString> {}, m_slices); + return resolve_slices(shell, Vector<String> {}, m_slices); - if (auto value = resolve_without_cast(shell); value != this) + if (auto value = TRY(resolve_without_cast(shell)); value != this) return value->resolve_as_list(shell); - char* env_value = getenv(m_name.characters()); + auto name = m_name.to_deprecated_string(); + char* env_value = getenv(name.characters()); if (env_value == nullptr) - return { resolve_slices(shell, "", m_slices) }; + return { resolve_slices(shell, Vector { String {} }, m_slices) }; - return { resolve_slices(shell, DeprecatedString { env_value }, m_slices) }; + return { resolve_slices(shell, Vector { TRY(String::from_utf8(StringView { env_value, strlen(env_value) })) }, m_slices) }; } -NonnullRefPtr<Value> SimpleVariableValue::resolve_without_cast(RefPtr<Shell> shell) +ErrorOr<NonnullRefPtr<Value>> SimpleVariableValue::resolve_without_cast(RefPtr<Shell> shell) { VERIFY(shell); @@ -3716,7 +3729,7 @@ NonnullRefPtr<Value> SimpleVariableValue::resolve_without_cast(RefPtr<Shell> she auto result = value.release_nonnull(); // If a slice is applied, add it. if (!m_slices.is_empty()) - result = result->with_slices(m_slices); + result = TRY(result->with_slices(m_slices)); return const_cast<Value&>(*result); } @@ -3728,76 +3741,76 @@ SpecialVariableValue::~SpecialVariableValue() { } -DeprecatedString SpecialVariableValue::resolve_as_string(RefPtr<Shell> shell) +ErrorOr<String> SpecialVariableValue::resolve_as_string(RefPtr<Shell> shell) { if (!shell) - return {}; + return String {}; - auto result = resolve_as_list(shell); + auto result = TRY(resolve_as_list(shell)); if (result.size() == 1) return result[0]; if (result.is_empty()) - return {}; + return String {}; return Value::resolve_as_string(shell); } -Vector<DeprecatedString> SpecialVariableValue::resolve_as_list(RefPtr<Shell> shell) +ErrorOr<Vector<String>> SpecialVariableValue::resolve_as_list(RefPtr<Shell> shell) { if (!shell) - return {}; + return Vector<String> {}; switch (m_name) { case '?': - return { resolve_slices(shell, DeprecatedString::number(shell->last_return_code.value_or(0)), m_slices) }; + return { resolve_slices(shell, Vector { TRY(String::number(shell->last_return_code.value_or(0))) }, m_slices) }; case '$': - return { resolve_slices(shell, DeprecatedString::number(getpid()), m_slices) }; + return { resolve_slices(shell, Vector { TRY(String::number(getpid())) }, m_slices) }; case '*': if (auto argv = shell->lookup_local_variable("ARGV"sv)) - return resolve_slices(shell, const_cast<Value&>(*argv).resolve_as_list(shell), m_slices); - return resolve_slices(shell, Vector<DeprecatedString> {}, m_slices); + return resolve_slices(shell, TRY(const_cast<Value&>(*argv).resolve_as_list(shell)), m_slices); + return resolve_slices(shell, Vector<String> {}, m_slices); case '#': if (auto argv = shell->lookup_local_variable("ARGV"sv)) { if (argv->is_list()) { auto list_argv = static_cast<AST::ListValue const*>(argv.ptr()); - return { resolve_slices(shell, DeprecatedString::number(list_argv->values().size()), m_slices) }; + return { resolve_slices(shell, Vector { TRY(String::number(list_argv->values().size())) }, m_slices) }; } - return { resolve_slices(shell, "1", m_slices) }; + return { resolve_slices(shell, Vector { String::from_utf8_short_string("1"sv) }, m_slices) }; } - return { resolve_slices(shell, "0", m_slices) }; + return { resolve_slices(shell, Vector { String::from_utf8_short_string("0"sv) }, m_slices) }; default: - return { resolve_slices(shell, "", m_slices) }; + return { resolve_slices(shell, Vector { String::from_utf8_short_string(""sv) }, m_slices) }; } } -NonnullRefPtr<Value> SpecialVariableValue::resolve_without_cast(RefPtr<Shell> shell) +ErrorOr<NonnullRefPtr<Value>> SpecialVariableValue::resolve_without_cast(RefPtr<Shell> shell) { if (!shell) return *this; - return make_ref_counted<ListValue>(resolve_as_list(shell)); + return try_make_ref_counted<ListValue>(TRY(resolve_as_list(shell))); } TildeValue::~TildeValue() { } -DeprecatedString TildeValue::resolve_as_string(RefPtr<Shell> shell) +ErrorOr<String> TildeValue::resolve_as_string(RefPtr<Shell> shell) { - return resolve_as_list(shell).first(); + return TRY(resolve_as_list(shell)).first(); } -Vector<DeprecatedString> TildeValue::resolve_as_list(RefPtr<Shell> shell) +ErrorOr<Vector<String>> TildeValue::resolve_as_list(RefPtr<Shell> shell) { StringBuilder builder; builder.append('~'); builder.append(m_username); if (!shell) - return { resolve_slices(shell, builder.to_deprecated_string(), m_slices) }; + return { resolve_slices(shell, Vector { TRY(builder.to_string()) }, m_slices) }; - return { resolve_slices(shell, shell->expand_tilde(builder.to_deprecated_string()), m_slices) }; + return { resolve_slices(shell, Vector { TRY(String::from_utf8(shell->expand_tilde(builder.to_deprecated_string()))) }, m_slices) }; } ErrorOr<NonnullRefPtr<Rewiring>> CloseRedirection::apply() const @@ -3811,7 +3824,7 @@ CloseRedirection::~CloseRedirection() ErrorOr<NonnullRefPtr<Rewiring>> PathRedirection::apply() const { - auto check_fd_and_return = [my_fd = this->fd](int fd, DeprecatedString const& path) -> ErrorOr<NonnullRefPtr<Rewiring>> { + auto check_fd_and_return = [my_fd = this->fd](int fd, String const& path) -> ErrorOr<NonnullRefPtr<Rewiring>> { if (fd < 0) { auto error = Error::from_errno(errno); dbgln("open() failed for '{}' with {}", path, error); @@ -3819,18 +3832,20 @@ ErrorOr<NonnullRefPtr<Rewiring>> PathRedirection::apply() const } return adopt_nonnull_ref_or_enomem(new (nothrow) Rewiring(fd, my_fd, Rewiring::Close::Old)); }; + + auto path_string = path.to_deprecated_string(); switch (direction) { case AST::PathRedirection::WriteAppend: - return check_fd_and_return(open(path.characters(), O_WRONLY | O_CREAT | O_APPEND, 0666), path); + return check_fd_and_return(open(path_string.characters(), O_WRONLY | O_CREAT | O_APPEND, 0666), path); case AST::PathRedirection::Write: - return check_fd_and_return(open(path.characters(), O_WRONLY | O_CREAT | O_TRUNC, 0666), path); + return check_fd_and_return(open(path_string.characters(), O_WRONLY | O_CREAT | O_TRUNC, 0666), path); case AST::PathRedirection::Read: - return check_fd_and_return(open(path.characters(), O_RDONLY), path); + return check_fd_and_return(open(path_string.characters(), O_RDONLY), path); case AST::PathRedirection::ReadWrite: - return check_fd_and_return(open(path.characters(), O_RDWR | O_CREAT, 0666), path); + return check_fd_and_return(open(path_string.characters(), O_RDWR | O_CREAT, 0666), path); } VERIFY_NOT_REACHED(); diff --git a/Userland/Shell/AST.h b/Userland/Shell/AST.h index 4d68c7848a..dd766d73da 100644 --- a/Userland/Shell/AST.h +++ b/Userland/Shell/AST.h @@ -9,11 +9,11 @@ #include "Forward.h" #include "Job.h" #include "NodeVisitor.h" -#include <AK/DeprecatedString.h> #include <AK/Format.h> #include <AK/NonnullRefPtr.h> #include <AK/RefCounted.h> #include <AK/RefPtr.h> +#include <AK/String.h> #include <AK/Types.h> #include <AK/Vector.h> #include <LibLine/Editor.h> @@ -60,7 +60,7 @@ struct Position { }; struct NameWithPosition { - DeprecatedString name; + String name; Position position; }; @@ -117,7 +117,7 @@ private: }; struct PathRedirection : public Redirection { - DeprecatedString path; + String path; int fd { -1 }; enum { Read, @@ -126,7 +126,7 @@ struct PathRedirection : public Redirection { ReadWrite, } direction { Read }; - static NonnullRefPtr<PathRedirection> create(DeprecatedString path, int fd, decltype(direction) direction) + static NonnullRefPtr<PathRedirection> create(String path, int fd, decltype(direction) direction) { return adopt_ref(*new PathRedirection(move(path), fd, direction)); } @@ -135,7 +135,7 @@ struct PathRedirection : public Redirection { virtual ~PathRedirection(); private: - PathRedirection(DeprecatedString path, int fd, decltype(direction) direction) + PathRedirection(String path, int fd, decltype(direction) direction) : path(move(path)) , fd(fd) , direction(direction) @@ -207,7 +207,7 @@ struct NodeWithAction { }; struct Command { - Vector<DeprecatedString> argv; + Vector<String> argv; NonnullRefPtrVector<Redirection> redirections; bool should_wait { true }; bool is_pipe_source { false }; @@ -227,13 +227,13 @@ struct HitTestResult { class Value : public RefCounted<Value> { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) = 0; - virtual DeprecatedString resolve_as_string(RefPtr<Shell> shell); - virtual Vector<Command> resolve_as_commands(RefPtr<Shell>); - virtual NonnullRefPtr<Value> resolve_without_cast(RefPtr<Shell>) { return *this; } - virtual NonnullRefPtr<Value> clone() const = 0; - virtual NonnullRefPtr<Value> with_slices(NonnullRefPtr<Slice> slice) const&; - virtual NonnullRefPtr<Value> with_slices(NonnullRefPtrVector<Slice> slices) const&; + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) = 0; + virtual ErrorOr<String> resolve_as_string(RefPtr<Shell> shell); + virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>); + virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) { return *this; } + virtual ErrorOr<NonnullRefPtr<Value>> clone() const = 0; + virtual ErrorOr<NonnullRefPtr<Value>> with_slices(NonnullRefPtr<Slice> slice) const&; + virtual ErrorOr<NonnullRefPtr<Value>> with_slices(NonnullRefPtrVector<Slice> slices) const&; virtual ~Value(); virtual bool is_command() const { return false; } virtual bool is_glob() const { return false; } @@ -253,9 +253,9 @@ protected: class CommandValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual Vector<Command> resolve_as_commands(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<CommandValue>(m_command)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<CommandValue>(m_command))->set_slices(m_slices); } virtual ~CommandValue(); virtual bool is_command() const override { return true; } CommandValue(Command command) @@ -263,7 +263,7 @@ public: { } - CommandValue(Vector<DeprecatedString> argv, Position position) + CommandValue(Vector<String> argv, Position position) : m_command({ move(argv), {}, true, false, true, false, nullptr, {}, move(position) }) { } @@ -274,9 +274,9 @@ private: class CommandSequenceValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual Vector<Command> resolve_as_commands(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<CommandSequenceValue>(m_contained_values)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<CommandSequenceValue>(m_contained_values))->set_slices(m_slices); } virtual ~CommandSequenceValue(); virtual bool is_command() const override { return true; } CommandSequenceValue(Vector<Command> commands) @@ -290,10 +290,10 @@ private: class JobValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); } - virtual DeprecatedString resolve_as_string(RefPtr<Shell>) override { return DeprecatedString::formatted("%{}", m_job->job_id()); } - virtual Vector<Command> resolve_as_commands(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); } - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<JobValue>(m_job)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); } + virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override { return String::formatted("%{}", m_job->job_id()); } + virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); } + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<JobValue>(m_job))->set_slices(m_slices); } virtual ~JobValue(); virtual bool is_job() const override { return true; } JobValue(RefPtr<Job> job) @@ -309,13 +309,13 @@ private: class ListValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> resolve_without_cast(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<ListValue>(m_contained_values)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<ListValue>(m_contained_values))->set_slices(m_slices); } virtual ~ListValue(); virtual bool is_list() const override { return true; } virtual bool is_list_without_resolution() const override { return true; } - ListValue(Vector<DeprecatedString> values); + ListValue(Vector<String> values); ListValue(NonnullRefPtrVector<Value> values) : m_contained_values(move(values)) { @@ -330,14 +330,14 @@ private: class StringValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual DeprecatedString resolve_as_string(RefPtr<Shell> shell) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<StringValue>(m_string, m_split, m_keep_empty)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<String> resolve_as_string(RefPtr<Shell> shell) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<StringValue>(m_string, m_split, m_keep_empty))->set_slices(m_slices); } virtual ~StringValue(); - virtual bool is_string() const override { return m_split.is_null(); } - virtual bool is_list() const override { return !m_split.is_null(); } - NonnullRefPtr<Value> resolve_without_cast(RefPtr<Shell>) override; - StringValue(DeprecatedString string, DeprecatedString split_by = {}, bool keep_empty = false) + virtual bool is_string() const override { return m_split.is_empty(); } + virtual bool is_list() const override { return !m_split.is_empty(); } + ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override; + StringValue(String string, String split_by = {}, bool keep_empty = false) : m_string(move(string)) , m_split(move(split_by)) , m_keep_empty(keep_empty) @@ -345,50 +345,50 @@ public: } private: - DeprecatedString m_string; - DeprecatedString m_split; + String m_string; + String m_split; bool m_keep_empty { false }; }; class GlobValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<GlobValue>(m_glob, m_generation_position)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<GlobValue>(m_glob, m_generation_position))->set_slices(m_slices); } virtual ~GlobValue(); virtual bool is_glob() const override { return true; } - GlobValue(DeprecatedString glob, Position position) + GlobValue(String glob, Position position) : m_glob(move(glob)) , m_generation_position(move(position)) { } private: - DeprecatedString m_glob; + String m_glob; Position m_generation_position; }; class SimpleVariableValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual DeprecatedString resolve_as_string(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> resolve_without_cast(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<SimpleVariableValue>(m_name)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<SimpleVariableValue>(m_name))->set_slices(m_slices); } virtual ~SimpleVariableValue(); - SimpleVariableValue(DeprecatedString name) + SimpleVariableValue(String name) : m_name(move(name)) { } private: - DeprecatedString m_name; + String m_name; }; class SpecialVariableValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual DeprecatedString resolve_as_string(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> resolve_without_cast(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<SpecialVariableValue>(m_name)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<SpecialVariableValue>(m_name))->set_slices(m_slices); } virtual ~SpecialVariableValue(); SpecialVariableValue(char name) : m_name(name) @@ -401,18 +401,18 @@ private: class TildeValue final : public Value { public: - virtual Vector<DeprecatedString> resolve_as_list(RefPtr<Shell>) override; - virtual DeprecatedString resolve_as_string(RefPtr<Shell>) override; - virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<TildeValue>(m_username)->set_slices(m_slices); } + virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override; + virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override; + virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<TildeValue>(m_username))->set_slices(m_slices); } virtual ~TildeValue(); virtual bool is_string() const override { return true; } - TildeValue(DeprecatedString name) + TildeValue(String name) : m_username(move(name)) { } private: - DeprecatedString m_username; + String m_username; }; class Node : public RefCounted<Node> { @@ -432,7 +432,7 @@ public: return { this, nullptr, nullptr }; return { nullptr, nullptr, nullptr }; } - virtual DeprecatedString class_name() const { return "Node"; } + virtual StringView class_name() const { return "Node"sv; } Node(Position); virtual ~Node() = default; @@ -519,14 +519,14 @@ protected: RefPtr<SyntaxError> m_syntax_error_node; }; -#define NODE(name) \ - virtual DeprecatedString class_name() const override \ - { \ - return #name; \ - } \ - virtual Kind kind() const override \ - { \ - return Kind::name; \ +#define NODE(name) \ + virtual StringView class_name() const override \ + { \ + return #name##sv; \ + } \ + virtual Kind kind() const override \ + { \ + return Kind::name; \ } class PathRedirectionNode : public Node { @@ -610,11 +610,11 @@ private: class BarewordLiteral final : public Node { public: - BarewordLiteral(Position, DeprecatedString); + BarewordLiteral(Position, String); virtual ~BarewordLiteral() = default; virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString const& text() const { return m_text; } + String const& text() const { return m_text; } private: NODE(BarewordLiteral); @@ -624,7 +624,7 @@ private: virtual bool is_bareword() const override { return true; } virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; } - DeprecatedString m_text; + String m_text; }; class BraceExpansion final : public Node { @@ -727,11 +727,11 @@ private: class Comment : public Node { public: - Comment(Position, DeprecatedString); + Comment(Position, String); virtual ~Comment(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString const& text() const { return m_text; } + String const& text() const { return m_text; } private: NODE(Comment); @@ -739,7 +739,7 @@ private: virtual RefPtr<Value> run(RefPtr<Shell>) override; virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override; - DeprecatedString m_text; + String m_text; }; class ContinuationControl final : public Node { @@ -890,11 +890,11 @@ private: class Glob final : public Node { public: - Glob(Position, DeprecatedString); + Glob(Position, String); virtual ~Glob(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString const& text() const { return m_text; } + String const& text() const { return m_text; } private: NODE(Glob); @@ -904,7 +904,7 @@ private: virtual bool is_glob() const override { return true; } virtual bool is_list() const override { return true; } - DeprecatedString m_text; + String m_text; }; struct HistorySelector { @@ -923,7 +923,7 @@ struct HistorySelector { EventKind kind { IndexFromStart }; size_t index { 0 }; Position text_position; - DeprecatedString text; + String text; } event; struct WordSelector { @@ -1025,7 +1025,7 @@ public: NonnullRefPtrVector<Node> const& arguments() const { return m_arguments; } auto const& function() const { return m_function; } - DeprecatedString const& function_name() const { return m_function.name; } + String const& function_name() const { return m_function.name; } Position const& function_position() const { return m_function.position; } bool has_closing_brace() const { return m_closing_brace_position.has_value(); } @@ -1067,7 +1067,7 @@ private: struct MatchEntry { Variant<NonnullRefPtrVector<Node>, Vector<Regex<ECMA262>>> options; - Optional<Vector<DeprecatedString>> match_names; + Optional<Vector<String>> match_names; Optional<Position> match_as_position; Vector<Position> pipe_positions; RefPtr<Node> body; @@ -1075,12 +1075,12 @@ struct MatchEntry { class MatchExpr final : public Node { public: - MatchExpr(Position, NonnullRefPtr<Node> expr, DeprecatedString name, Optional<Position> as_position, Vector<MatchEntry> entries); + MatchExpr(Position, NonnullRefPtr<Node> expr, String name, Optional<Position> as_position, Vector<MatchEntry> entries); virtual ~MatchExpr(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } NonnullRefPtr<Node> const& matched_expr() const { return m_matched_expr; } - DeprecatedString const& expr_name() const { return m_expr_name; } + String const& expr_name() const { return m_expr_name; } Vector<MatchEntry> const& entries() const { return m_entries; } Optional<Position> const& as_position() const { return m_as_position; } @@ -1094,7 +1094,7 @@ private: virtual bool should_override_execution_in_current_process() const override { return true; } NonnullRefPtr<Node> m_matched_expr; - DeprecatedString m_expr_name; + String m_expr_name; Optional<Position> m_as_position; Vector<MatchEntry> m_entries; }; @@ -1273,11 +1273,11 @@ protected: class SimpleVariable final : public VariableNode { public: - SimpleVariable(Position, DeprecatedString); + SimpleVariable(Position, String); virtual ~SimpleVariable(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString const& name() const { return m_name; } + String const& name() const { return m_name; } private: NODE(SimpleVariable); @@ -1288,7 +1288,7 @@ private: virtual HitTestResult hit_test_position(size_t) const override; virtual bool is_simple_variable() const override { return true; } - DeprecatedString m_name; + String m_name; }; class SpecialVariable final : public VariableNode { @@ -1338,11 +1338,11 @@ private: class Heredoc final : public Node { public: - Heredoc(Position, DeprecatedString end, bool allow_interpolation, bool deindent, Optional<int> target_fd = {}); + Heredoc(Position, String end, bool allow_interpolation, bool deindent, Optional<int> target_fd = {}); virtual ~Heredoc(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString const& end() const { return m_end; } + String const& end() const { return m_end; } bool allow_interpolation() const { return m_allows_interpolation; } bool deindent() const { return m_deindent; } Optional<int> target_fd() const { return m_target_fd; } @@ -1365,7 +1365,7 @@ private: virtual HitTestResult hit_test_position(size_t) const override; virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }; - DeprecatedString m_end; + String m_end; bool m_allows_interpolation { false }; bool m_deindent { false }; Optional<int> m_target_fd; @@ -1380,11 +1380,11 @@ public: DoubleQuotes, }; - StringLiteral(Position, DeprecatedString, EnclosureType); + StringLiteral(Position, String, EnclosureType); virtual ~StringLiteral(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString const& text() const { return m_text; } + String const& text() const { return m_text; } EnclosureType enclosure_type() const { return m_enclosure_type; } private: @@ -1394,7 +1394,7 @@ private: virtual void highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override; virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }; - DeprecatedString m_text; + String m_text; EnclosureType m_enclosure_type; }; @@ -1420,11 +1420,11 @@ private: class SyntaxError final : public Node { public: - SyntaxError(Position, DeprecatedString, bool is_continuable = false); + SyntaxError(Position, String, bool is_continuable = false); virtual ~SyntaxError(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString const& error_text() const { return m_syntax_error_text; } + String const& error_text() const { return m_syntax_error_text; } bool is_continuable() const { return m_is_continuable; } virtual void clear_syntax_error() override @@ -1449,7 +1449,7 @@ private: virtual HitTestResult hit_test_position(size_t) const override { return { nullptr, nullptr, nullptr }; } virtual SyntaxError& syntax_error_node() override; - DeprecatedString m_syntax_error_text; + String m_syntax_error_text; bool m_is_continuable { false }; bool m_is_cleared { false }; }; @@ -1473,11 +1473,11 @@ private: class Tilde final : public Node { public: - Tilde(Position, DeprecatedString); + Tilde(Position, String); virtual ~Tilde(); virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); } - DeprecatedString text() const; + String text() const; private: NODE(Tilde); @@ -1488,7 +1488,7 @@ private: virtual HitTestResult hit_test_position(size_t) const override; virtual bool is_tilde() const override { return true; } - DeprecatedString m_username; + String m_username; }; class VariableDeclarations final : public Node { diff --git a/Userland/Shell/Builtin.cpp b/Userland/Shell/Builtin.cpp index a4e78b8604..0e51867ecd 100644 --- a/Userland/Shell/Builtin.cpp +++ b/Userland/Shell/Builtin.cpp @@ -554,7 +554,7 @@ int Shell::builtin_export(int argc, char const** argv) if (parts.size() == 1) { auto value = lookup_local_variable(parts[0]); if (value) { - auto values = const_cast<AST::Value&>(*value).resolve_as_list(*this); + auto values = const_cast<AST::Value&>(*value).resolve_as_list(*this).release_value_but_fixme_should_propagate_errors(); StringBuilder builder; builder.join(' ', values); parts.append(builder.to_deprecated_string()); @@ -963,7 +963,7 @@ int Shell::builtin_shift(int argc, char const** argv) int Shell::builtin_source(int argc, char const** argv) { char const* file_to_source = nullptr; - Vector<DeprecatedString> args; + Vector<StringView> args; Core::ArgsParser parser; parser.add_positional_argument(file_to_source, "File to read commands from", "path"); @@ -978,8 +978,14 @@ int Shell::builtin_source(int argc, char const** argv) set_local_variable("ARGV", const_cast<AST::Value&>(*previous_argv)); } }; - if (!args.is_empty()) - set_local_variable("ARGV", AST::make_ref_counted<AST::ListValue>(move(args))); + if (!args.is_empty()) { + Vector<String> arguments; + arguments.ensure_capacity(args.size()); + for (auto& arg : args) + arguments.append(String::from_utf8(arg).release_value_but_fixme_should_propagate_errors()); + + set_local_variable("ARGV", AST::make_ref_counted<AST::ListValue>(move(arguments))); + } if (!run_file(file_to_source, true)) return 126; @@ -989,14 +995,14 @@ int Shell::builtin_source(int argc, char const** argv) int Shell::builtin_time(int argc, char const** argv) { - AST::Command command; + Vector<StringView> args; int number_of_iterations = 1; Core::ArgsParser parser; parser.add_option(number_of_iterations, "Number of iterations", "iterations", 'n', "iterations"); parser.set_stop_on_first_non_option(true); - parser.add_positional_argument(command.argv, "Command to execute with arguments", "command", Core::ArgsParser::Required::Yes); + parser.add_positional_argument(args, "Command to execute with arguments", "command", Core::ArgsParser::Required::Yes); if (!parser.parse(argc, const_cast<char**>(argv), Core::ArgsParser::FailureBehavior::PrintUsage)) return 1; @@ -1004,6 +1010,11 @@ int Shell::builtin_time(int argc, char const** argv) if (number_of_iterations < 1) return 1; + AST::Command command; + command.argv.ensure_capacity(args.size()); + for (auto& arg : args) + command.argv.append(String::from_utf8(arg).release_value_but_fixme_should_propagate_errors()); + auto commands = expand_aliases({ move(command) }); AK::Statistics iteration_times; @@ -1163,7 +1174,7 @@ int Shell::builtin_not(int argc, char const** argv) AST::Command command; for (size_t i = 1; i < (size_t)argc; ++i) - command.argv.append(argv[i]); + command.argv.append(String::from_utf8(StringView { argv[i], strlen(argv[i]) }).release_value_but_fixme_should_propagate_errors()); auto commands = expand_aliases({ move(command) }); int exit_code = 1; @@ -1182,24 +1193,24 @@ int Shell::builtin_not(int argc, char const** argv) int Shell::builtin_kill(int argc, char const** argv) { // Simply translate the arguments and pass them to `kill' - Vector<DeprecatedString> replaced_values; + Vector<String> replaced_values; auto kill_path = Core::DeprecatedFile::resolve_executable_from_environment("kill"sv); if (!kill_path.has_value()) { warnln("kill: `kill' not found in PATH"); return 126; } - replaced_values.append(kill_path.release_value()); + replaced_values.append(String::from_deprecated_string(kill_path.release_value()).release_value_but_fixme_should_propagate_errors()); for (auto i = 1; i < argc; ++i) { if (auto job_id = resolve_job_spec({ argv[i], strlen(argv[1]) }); job_id.has_value()) { auto job = find_job(job_id.value()); if (job) { - replaced_values.append(DeprecatedString::number(job->pid())); + replaced_values.append(String::number(job->pid()).release_value_but_fixme_should_propagate_errors()); } else { warnln("kill: Job with pid {} not found", job_id.value()); return 1; } } else { - replaced_values.append(argv[i]); + replaced_values.append(String::from_deprecated_string(argv[i]).release_value_but_fixme_should_propagate_errors()); } } @@ -1230,9 +1241,13 @@ bool Shell::run_builtin(const AST::Command& command, NonnullRefPtrVector<AST::Re if (!has_builtin(command.argv.first())) return false; + // FIXME: Make all the functions above take the more idiomatic (Main::Arguments) parameters, and remove this gross conversion. Vector<char const*> argv; - for (auto& arg : command.argv) - argv.append(arg.characters()); + Vector<DeprecatedString> args; + for (auto& arg : command.argv) { + args.append(arg.to_deprecated_string()); + argv.append(args.last().characters()); + } argv.append(nullptr); @@ -1302,19 +1317,19 @@ int Shell::builtin_argsparser_parse(int argc, char const** argv) auto try_convert = [](StringView value, Type type) -> Optional<RefPtr<AST::Value>> { switch (type) { case Type::Bool: - return AST::make_ref_counted<AST::StringValue>("true"); + return AST::make_ref_counted<AST::StringValue>(String::from_utf8("true"sv).release_value_but_fixme_should_propagate_errors()); case Type::String: - return AST::make_ref_counted<AST::StringValue>(value); + return AST::make_ref_counted<AST::StringValue>(String::from_utf8(value).release_value_but_fixme_should_propagate_errors()); case Type::I32: if (auto number = value.to_int(); number.has_value()) - return AST::make_ref_counted<AST::StringValue>(DeprecatedString::number(*number)); + return AST::make_ref_counted<AST::StringValue>(String::number(*number).release_value_but_fixme_should_propagate_errors()); warnln("Invalid value for type i32: {}", value); return {}; case Type::U32: case Type::Size: if (auto number = value.to_uint(); number.has_value()) - return AST::make_ref_counted<AST::StringValue>(DeprecatedString::number(*number)); + return AST::make_ref_counted<AST::StringValue>(String::number(*number).release_value_but_fixme_should_propagate_errors()); warnln("Invalid value for type u32|size: {}", value); return {}; @@ -1327,7 +1342,7 @@ int Shell::builtin_argsparser_parse(int argc, char const** argv) return {}; } - return AST::make_ref_counted<AST::StringValue>(DeprecatedString::number(number)); + return AST::make_ref_counted<AST::StringValue>(String::number(number).release_value_but_fixme_should_propagate_errors()); } default: VERIFY_NOT_REACHED(); @@ -1337,8 +1352,8 @@ int Shell::builtin_argsparser_parse(int argc, char const** argv) auto enlist = [&](auto name, auto value) -> NonnullRefPtr<AST::Value> { auto variable = lookup_local_variable(name); if (variable) { - auto list = const_cast<AST::Value&>(*variable).resolve_as_list(*this); - auto new_value = value->resolve_as_string(*this); + auto list = const_cast<AST::Value&>(*variable).resolve_as_list(*this).release_value_but_fixme_should_propagate_errors(); + auto new_value = value->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); list.append(move(new_value)); return make_ref_counted<AST::ListValue>(move(list)); } @@ -1482,7 +1497,7 @@ int Shell::builtin_argsparser_parse(int argc, char const** argv) } if (type == Type::Bool) - set_local_variable(current_variable, make_ref_counted<AST::StringValue>("false"), true); + set_local_variable(current_variable, make_ref_counted<AST::StringValue>(String::from_utf8("false"sv).release_value_but_fixme_should_propagate_errors()), true); return true; }, }); diff --git a/Userland/Shell/Formatter.cpp b/Userland/Shell/Formatter.cpp index 9f7aea7820..3c1ac9aad3 100644 --- a/Userland/Shell/Formatter.cpp +++ b/Userland/Shell/Formatter.cpp @@ -598,7 +598,7 @@ void Formatter::visit(const AST::MatchExpr* node) if (!first) current_builder().append(" | "sv); first = false; - auto node = make_ref_counted<AST::BarewordLiteral>(AST::Position {}, option.pattern_value); + auto node = make_ref_counted<AST::BarewordLiteral>(AST::Position {}, String::from_utf8(option.pattern_value).release_value_but_fixme_should_propagate_errors()); node->visit(*this); } }); @@ -791,7 +791,7 @@ void Formatter::visit(const AST::StringLiteral* node) current_builder().append("'"sv); if (m_options.in_double_quotes && !m_options.in_heredoc) { - for (auto ch : node->text()) { + for (auto ch : node->text().bytes_as_string_view()) { switch (ch) { case '"': case '\\': diff --git a/Userland/Shell/Formatter.h b/Userland/Shell/Formatter.h index ac58e54ec2..00e29bf889 100644 --- a/Userland/Shell/Formatter.h +++ b/Userland/Shell/Formatter.h @@ -6,6 +6,7 @@ #pragma once +#include "AST.h" #include "NodeVisitor.h" #include <AK/DeprecatedString.h> #include <AK/Forward.h> diff --git a/Userland/Shell/ImmediateFunctions.cpp b/Userland/Shell/ImmediateFunctions.cpp index 647bafb80d..7a0d1e2f31 100644 --- a/Userland/Shell/ImmediateFunctions.cpp +++ b/Userland/Shell/ImmediateFunctions.cpp @@ -59,7 +59,7 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin if (expr_node->is_list()) mode = List; else if (expr_node->is_simple_variable()) // "Look inside" variables - mode = const_cast<AST::Node*>(expr_node)->run(this)->resolve_without_cast(this)->is_list_without_resolution() ? List : String; + mode = const_cast<AST::Node*>(expr_node)->run(this)->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors()->is_list_without_resolution() ? List : String; else if (is<AST::ImmediateExpression>(expr_node)) mode = List; else @@ -67,7 +67,7 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin } auto value_with_number = [&](auto number) -> NonnullRefPtr<AST::Node> { - return AST::make_ref_counted<AST::BarewordLiteral>(invoking_node.position(), DeprecatedString::number(number)); + return AST::make_ref_counted<AST::BarewordLiteral>(invoking_node.position(), String::number(number).release_value_but_fixme_should_propagate_errors()); }; auto do_across = [&](StringView mode_name, auto& values) { @@ -80,9 +80,9 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin // ImmediateExpression(length <mode_name> <entry>) resulting_nodes.unchecked_append(AST::make_ref_counted<AST::ImmediateExpression>( expr_node->position(), - AST::NameWithPosition { "length", invoking_node.function_position() }, + AST::NameWithPosition { String::from_utf8("length"sv).release_value_but_fixme_should_propagate_errors(), invoking_node.function_position() }, NonnullRefPtrVector<AST::Node> { Vector<NonnullRefPtr<AST::Node>> { - static_cast<NonnullRefPtr<AST::Node>>(AST::make_ref_counted<AST::BarewordLiteral>(expr_node->position(), mode_name)), + static_cast<NonnullRefPtr<AST::Node>>(AST::make_ref_counted<AST::BarewordLiteral>(expr_node->position(), String::from_utf8(mode_name).release_value_but_fixme_should_propagate_errors())), AST::make_ref_counted<AST::SyntheticNode>(expr_node->position(), NonnullRefPtr<AST::Value>(entry)), } }, expr_node->position())); @@ -100,7 +100,7 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin if (!value) return value_with_number(0); - value = value->resolve_without_cast(this); + value = value->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors(); if (auto list = dynamic_cast<AST::ListValue*>(value.ptr())) { if (across) @@ -109,7 +109,7 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin return value_with_number(list->values().size()); } - auto list = value->resolve_as_list(this); + auto list = value->resolve_as_list(this).release_value_but_fixme_should_propagate_errors(); if (!across) return value_with_number(list.size()); @@ -145,7 +145,7 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin if (!value) return value_with_number(0); - value = value->resolve_without_cast(*this); + value = value->resolve_without_cast(*this).release_value_but_fixme_should_propagate_errors(); if (auto list = dynamic_cast<AST::ListValue*>(value.ptr())) { if (!across) @@ -165,7 +165,7 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin } // Evaluate the nodes and substitute with the lengths. - auto list = value->resolve_as_list(this); + auto list = value->resolve_as_list(this).release_value_but_fixme_should_propagate_errors(); if (!expr_node->is_list()) { if (list.size() == 1) { @@ -173,7 +173,7 @@ RefPtr<AST::Node> Shell::immediate_length_impl(AST::ImmediateExpression& invokin goto raise_no_list_allowed; // This is the normal case, the expression is a normal non-list expression. - return value_with_number(list.first().length()); + return value_with_number(list.first().bytes_as_string_view().length()); } // This can be hit by asking for the length of a command list (e.g. `(>/dev/null)`) @@ -208,7 +208,7 @@ RefPtr<AST::Node> Shell::immediate_regex_replace(AST::ImmediateExpression& invok auto pattern = const_cast<AST::Node&>(arguments[0]).run(this); auto replacement = const_cast<AST::Node&>(arguments[1]).run(this); - auto value = const_cast<AST::Node&>(arguments[2]).run(this)->resolve_without_cast(this); + auto value = const_cast<AST::Node&>(arguments[2]).run(this)->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors(); if (!pattern->is_string()) { raise_error(ShellError::EvaluatedSyntaxError, "Expected the regex_replace pattern to be a string", arguments[0].position()); @@ -225,10 +225,13 @@ RefPtr<AST::Node> Shell::immediate_regex_replace(AST::ImmediateExpression& invok return nullptr; } - Regex<PosixExtendedParser> re { pattern->resolve_as_list(this).first() }; - auto result = re.replace(value->resolve_as_list(this)[0], replacement->resolve_as_list(this)[0], PosixFlags::Global | PosixFlags::Multiline | PosixFlags::Unicode); + Regex<PosixExtendedParser> re { pattern->resolve_as_list(this).release_value_but_fixme_should_propagate_errors().first().to_deprecated_string() }; + auto result = re.replace( + value->resolve_as_list(this).release_value_but_fixme_should_propagate_errors()[0], + replacement->resolve_as_list(this).release_value_but_fixme_should_propagate_errors()[0], + PosixFlags::Global | PosixFlags::Multiline | PosixFlags::Unicode); - return AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), move(result), AST::StringLiteral::EnclosureType::None); + return AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), String::from_utf8(result).release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::None); } RefPtr<AST::Node> Shell::immediate_remove_suffix(AST::ImmediateExpression& invoking_node, NonnullRefPtrVector<AST::Node> const& arguments) @@ -239,24 +242,25 @@ RefPtr<AST::Node> Shell::immediate_remove_suffix(AST::ImmediateExpression& invok } auto suffix = const_cast<AST::Node&>(arguments[0]).run(this); - auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this); + auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors(); if (!suffix->is_string()) { raise_error(ShellError::EvaluatedSyntaxError, "Expected the remove_suffix suffix string to be a string", arguments[0].position()); return nullptr; } - auto suffix_str = suffix->resolve_as_list(this)[0]; - auto values = value->resolve_as_list(this); + auto suffix_str = suffix->resolve_as_list(this).release_value_but_fixme_should_propagate_errors()[0]; + auto values = value->resolve_as_list(this).release_value_but_fixme_should_propagate_errors(); Vector<NonnullRefPtr<AST::Node>> nodes; for (auto& value_str : values) { - StringView removed { value_str }; + String removed = String::from_utf8(value_str).release_value_but_fixme_should_propagate_errors(); - if (value_str.ends_with(suffix_str)) - removed = removed.substring_view(0, value_str.length() - suffix_str.length()); - nodes.append(AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), removed, AST::StringLiteral::EnclosureType::None)); + if (value_str.bytes_as_string_view().ends_with(suffix_str)) + removed = removed.substring_from_byte_offset(0, value_str.bytes_as_string_view().length() - suffix_str.bytes_as_string_view().length()).release_value_but_fixme_should_propagate_errors(); + + nodes.append(AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), move(removed), AST::StringLiteral::EnclosureType::None)); } return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(nodes)); @@ -270,24 +274,24 @@ RefPtr<AST::Node> Shell::immediate_remove_prefix(AST::ImmediateExpression& invok } auto prefix = const_cast<AST::Node&>(arguments[0]).run(this); - auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this); + auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors(); if (!prefix->is_string()) { raise_error(ShellError::EvaluatedSyntaxError, "Expected the remove_prefix prefix string to be a string", arguments[0].position()); return nullptr; } - auto prefix_str = prefix->resolve_as_list(this)[0]; - auto values = value->resolve_as_list(this); + auto prefix_str = prefix->resolve_as_list(this).release_value_but_fixme_should_propagate_errors()[0]; + auto values = value->resolve_as_list(this).release_value_but_fixme_should_propagate_errors(); Vector<NonnullRefPtr<AST::Node>> nodes; for (auto& value_str : values) { - StringView removed { value_str }; + String removed = String::from_utf8(value_str).release_value_but_fixme_should_propagate_errors(); - if (value_str.starts_with(prefix_str)) - removed = removed.substring_view(prefix_str.length()); - nodes.append(AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), removed, AST::StringLiteral::EnclosureType::None)); + if (value_str.bytes_as_string_view().starts_with(prefix_str)) + removed = removed.substring_from_byte_offset(prefix_str.bytes_as_string_view().length()).release_value_but_fixme_should_propagate_errors(); + nodes.append(AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), move(removed), AST::StringLiteral::EnclosureType::None)); } return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), move(nodes)); @@ -301,14 +305,14 @@ RefPtr<AST::Node> Shell::immediate_split(AST::ImmediateExpression& invoking_node } auto delimiter = const_cast<AST::Node&>(arguments[0]).run(this); - auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this); + auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors(); if (!delimiter->is_string()) { raise_error(ShellError::EvaluatedSyntaxError, "Expected the split delimiter string to be a string", arguments[0].position()); return nullptr; } - auto delimiter_str = delimiter->resolve_as_list(this)[0]; + auto delimiter_str = delimiter->resolve_as_list(this).release_value_but_fixme_should_propagate_errors()[0]; auto transform = [&](auto const& values) { // Translate to a list of applications of `split <delimiter>` @@ -334,25 +338,25 @@ RefPtr<AST::Node> Shell::immediate_split(AST::ImmediateExpression& invoking_node } // Otherwise, just resolve to a list and transform that. - auto list = value->resolve_as_list(this); + auto list = value->resolve_as_list(this).release_value_but_fixme_should_propagate_errors(); if (!value->is_list()) { if (list.is_empty()) return AST::make_ref_counted<AST::ListConcatenate>(invoking_node.position(), NonnullRefPtrVector<AST::Node> {}); auto& value = list.first(); - Vector<DeprecatedString> split_strings; + Vector<String> split_strings; if (delimiter_str.is_empty()) { StringBuilder builder; for (auto code_point : Utf8View { value }) { builder.append_code_point(code_point); - split_strings.append(builder.to_deprecated_string()); + split_strings.append(builder.to_string().release_value_but_fixme_should_propagate_errors()); builder.clear(); } } else { auto split = StringView { value }.split_view(delimiter_str, options.inline_exec_keep_empty_segments ? SplitBehavior::KeepEmpty : SplitBehavior::Nothing); split_strings.ensure_capacity(split.size()); for (auto& entry : split) - split_strings.append(entry); + split_strings.append(String::from_utf8(entry).release_value_but_fixme_should_propagate_errors()); } return AST::make_ref_counted<AST::SyntheticNode>(invoking_node.position(), AST::make_ref_counted<AST::ListValue>(move(split_strings))); } @@ -368,12 +372,12 @@ RefPtr<AST::Node> Shell::immediate_concat_lists(AST::ImmediateExpression& invoki if (auto* list = dynamic_cast<const AST::ListConcatenate*>(&argument)) { result.extend(list->list()); } else { - auto list_of_values = const_cast<AST::Node&>(argument).run(this)->resolve_without_cast(this); + auto list_of_values = const_cast<AST::Node&>(argument).run(this)->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors(); if (auto* list = dynamic_cast<AST::ListValue*>(list_of_values.ptr())) { for (auto& entry : static_cast<Vector<NonnullRefPtr<AST::Value>>&>(list->values())) result.append(AST::make_ref_counted<AST::SyntheticNode>(argument.position(), entry)); } else { - auto values = list_of_values->resolve_as_list(this); + auto values = list_of_values->resolve_as_list(this).release_value_but_fixme_should_propagate_errors(); for (auto& entry : values) result.append(AST::make_ref_counted<AST::StringLiteral>(argument.position(), entry, AST::StringLiteral::EnclosureType::None)); } @@ -391,7 +395,7 @@ RefPtr<AST::Node> Shell::immediate_filter_glob(AST::ImmediateExpression& invokin return nullptr; } - auto glob_list = const_cast<AST::Node&>(arguments[0]).run(*this)->resolve_as_list(*this); + auto glob_list = const_cast<AST::Node&>(arguments[0]).run(*this)->resolve_as_list(*this).release_value_but_fixme_should_propagate_errors(); if (glob_list.size() != 1) { raise_error(ShellError::EvaluatedSyntaxError, "Expected the <glob> argument to filter_glob to be a single string", arguments[0].position()); return nullptr; @@ -402,18 +406,18 @@ RefPtr<AST::Node> Shell::immediate_filter_glob(AST::ImmediateExpression& invokin NonnullRefPtrVector<AST::Node> result; const_cast<AST::Node&>(list_node).for_each_entry(*this, [&](NonnullRefPtr<AST::Value> entry) { - auto value = entry->resolve_as_list(*this); + auto value = entry->resolve_as_list(*this).release_value_but_fixme_should_propagate_errors(); if (value.size() == 0) return IterationDecision::Continue; if (value.size() == 1) { - if (!value.first().matches(glob)) + if (!value.first().bytes_as_string_view().matches(glob)) return IterationDecision::Continue; result.append(AST::make_ref_counted<AST::StringLiteral>(arguments[1].position(), value.first(), AST::StringLiteral::EnclosureType::None)); return IterationDecision::Continue; } for (auto& entry : value) { - if (entry.matches(glob)) { + if (entry.bytes_as_string_view().matches(glob)) { NonnullRefPtrVector<AST::Node> nodes; for (auto& string : value) nodes.append(AST::make_ref_counted<AST::StringLiteral>(arguments[1].position(), string, AST::StringLiteral::EnclosureType::None)); @@ -440,17 +444,17 @@ RefPtr<AST::Node> Shell::immediate_join(AST::ImmediateExpression& invoking_node, return nullptr; } - auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this); + auto value = const_cast<AST::Node&>(arguments[1]).run(this)->resolve_without_cast(this).release_value_but_fixme_should_propagate_errors(); if (!value->is_list()) { raise_error(ShellError::EvaluatedSyntaxError, "Expected the joined list to be a list", arguments[1].position()); return nullptr; } - auto delimiter_str = delimiter->resolve_as_list(this)[0]; + auto delimiter_str = delimiter->resolve_as_list(this).release_value_but_fixme_should_propagate_errors()[0]; StringBuilder builder; - builder.join(delimiter_str, value->resolve_as_list(*this)); + builder.join(delimiter_str, value->resolve_as_list(*this).release_value_but_fixme_should_propagate_errors()); - return AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), builder.to_deprecated_string(), AST::StringLiteral::EnclosureType::None); + return AST::make_ref_counted<AST::StringLiteral>(invoking_node.position(), builder.to_string().release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::None); } RefPtr<AST::Node> Shell::immediate_value_or_default(AST::ImmediateExpression& invoking_node, NonnullRefPtrVector<AST::Node> const& arguments) @@ -460,7 +464,7 @@ RefPtr<AST::Node> Shell::immediate_value_or_default(AST::ImmediateExpression& in return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (!local_variable_or(name, ""sv).is_empty()) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); @@ -474,12 +478,12 @@ RefPtr<AST::Node> Shell::immediate_assign_default(AST::ImmediateExpression& invo return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (!local_variable_or(name, ""sv).is_empty()) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); - auto value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_without_cast(*this); - set_local_variable(name, value); + auto value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_without_cast(*this).release_value_but_fixme_should_propagate_errors(); + set_local_variable(name.to_deprecated_string(), value); return make_ref_counted<AST::SyntheticNode>(invoking_node.position(), value); } @@ -491,15 +495,15 @@ RefPtr<AST::Node> Shell::immediate_error_if_empty(AST::ImmediateExpression& invo return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (!local_variable_or(name, ""sv).is_empty()) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); - auto error_value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_as_string(*this); + auto error_value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (error_value.is_empty()) - error_value = DeprecatedString::formatted("Expected {} to be non-empty", name); + error_value = String::formatted("Expected {} to be non-empty", name).release_value_but_fixme_should_propagate_errors(); - raise_error(ShellError::EvaluatedSyntaxError, error_value, invoking_node.position()); + raise_error(ShellError::EvaluatedSyntaxError, error_value.bytes_as_string_view(), invoking_node.position()); return nullptr; } @@ -510,8 +514,8 @@ RefPtr<AST::Node> Shell::immediate_null_or_alternative(AST::ImmediateExpression& return nullptr; } - auto value = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_without_cast(*this); - if ((value->is_string() && value->resolve_as_string(*this).is_empty()) || (value->is_list() && value->resolve_as_list(*this).is_empty())) + auto value = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_without_cast(*this).release_value_but_fixme_should_propagate_errors(); + if ((value->is_string() && value->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors().is_empty()) || (value->is_list() && value->resolve_as_list(*this).release_value_but_fixme_should_propagate_errors().is_empty())) return make_ref_counted<AST::SyntheticNode>(invoking_node.position(), value); return arguments.last(); @@ -524,7 +528,7 @@ RefPtr<AST::Node> Shell::immediate_defined_value_or_default(AST::ImmediateExpres return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (!find_frame_containing_local_variable(name)) return arguments.last(); @@ -538,12 +542,12 @@ RefPtr<AST::Node> Shell::immediate_assign_defined_default(AST::ImmediateExpressi return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (find_frame_containing_local_variable(name)) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); - auto value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_without_cast(*this); - set_local_variable(name, value); + auto value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_without_cast(*this).release_value_but_fixme_should_propagate_errors(); + set_local_variable(name.to_deprecated_string(), value); return make_ref_counted<AST::SyntheticNode>(invoking_node.position(), value); } @@ -555,15 +559,15 @@ RefPtr<AST::Node> Shell::immediate_error_if_unset(AST::ImmediateExpression& invo return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (find_frame_containing_local_variable(name)) return make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); - auto error_value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_as_string(*this); + auto error_value = const_cast<AST::Node&>(arguments.last()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (error_value.is_empty()) - error_value = DeprecatedString::formatted("Expected {} to be set", name); + error_value = String::formatted("Expected {} to be set", name).release_value_but_fixme_should_propagate_errors(); - raise_error(ShellError::EvaluatedSyntaxError, error_value, invoking_node.position()); + raise_error(ShellError::EvaluatedSyntaxError, error_value.bytes_as_string_view(), invoking_node.position()); return nullptr; } @@ -574,7 +578,7 @@ RefPtr<AST::Node> Shell::immediate_null_if_unset_or_alternative(AST::ImmediateEx return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); if (!find_frame_containing_local_variable(name)) return arguments.last(); @@ -588,7 +592,7 @@ RefPtr<AST::Node> Shell::immediate_reexpand(AST::ImmediateExpression& invoking_n return nullptr; } - auto value = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto value = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); return parse(value, m_is_interactive, false); } @@ -599,7 +603,7 @@ RefPtr<AST::Node> Shell::immediate_length_of_variable(AST::ImmediateExpression& return nullptr; } - auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this); + auto name = const_cast<AST::Node&>(arguments.first()).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); auto variable = make_ref_counted<AST::SimpleVariable>(invoking_node.position(), name); return immediate_length_impl( diff --git a/Userland/Shell/Parser.cpp b/Userland/Shell/Parser.cpp index 43ec26b497..ec9ec35f99 100644 --- a/Userland/Shell/Parser.cpp +++ b/Userland/Shell/Parser.cpp @@ -132,7 +132,7 @@ RefPtr<AST::Node> Parser::parse() auto error_start = push_start(); while (!at_end()) consume(); - auto syntax_error_node = create<AST::SyntaxError>("Unexpected tokens past the end"); + auto syntax_error_node = create<AST::SyntaxError>(String::from_utf8("Unexpected tokens past the end"sv).release_value_but_fixme_should_propagate_errors()); if (!toplevel) toplevel = move(syntax_error_node); else if (!toplevel->is_syntax_error()) @@ -217,7 +217,7 @@ Parser::SequenceParseResult Parser::parse_sequence() error_builder.appendff(", {} (at {}:{})", entry.end, entry.node->position().start_line.line_column, entry.node->position().start_line.line_number); first = false; } - left.append(create<AST::SyntaxError>(error_builder.to_deprecated_string(), true)); + left.append(create<AST::SyntaxError>(error_builder.to_string().release_value_but_fixme_should_propagate_errors(), true)); // Just read the rest of the newlines goto discard_terminators; } @@ -314,7 +314,7 @@ RefPtr<AST::Node> Parser::parse_variable_decls() return nullptr; } - auto name_expr = create<AST::BarewordLiteral>(move(var_name)); + auto name_expr = create<AST::BarewordLiteral>(String::from_utf8(var_name).release_value_but_fixme_should_propagate_errors()); auto start = push_start(); auto expression = parse_expression(); @@ -326,14 +326,14 @@ RefPtr<AST::Node> Parser::parse_variable_decls() if (!command) restore_to(*start); else if (!expect(')')) - command->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating close paren", true)); + command->set_is_syntax_error(*create<AST::SyntaxError>(String::from_utf8("Expected a terminating close paren"sv).release_value_but_fixme_should_propagate_errors(), true)); expression = command; } } if (!expression) { if (is_whitespace(peek())) { auto string_start = push_start(); - expression = create<AST::StringLiteral>("", AST::StringLiteral::EnclosureType::None); + expression = create<AST::StringLiteral>(String {}, AST::StringLiteral::EnclosureType::None); } else { restore_to(pos_before_name.offset, pos_before_name.line); return nullptr; @@ -391,7 +391,7 @@ RefPtr<AST::Node> Parser::parse_function_decl() // FIXME: Should this be a syntax error, or just return? return restore(); } - arguments.append({ arg_name, { name_offset, m_offset, start_line, line() } }); + arguments.append({ String::from_utf8(arg_name).release_value_but_fixme_should_propagate_errors(), { name_offset, m_offset, start_line, line() } }); } consume_while(is_any_of("\n\t "sv)); @@ -400,12 +400,12 @@ RefPtr<AST::Node> Parser::parse_function_decl() RefPtr<AST::Node> syntax_error; { auto obrace_error_start = push_start(); - syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a function body", true); + syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected an open brace '{' to start a function body"sv).release_value_but_fixme_should_propagate_errors(), true); } if (!expect('{')) { return create<AST::FunctionDeclaration>( AST::NameWithPosition { - move(function_name), + String::from_utf8(function_name).release_value_but_fixme_should_propagate_errors(), { pos_before_name.offset, pos_after_name.offset, pos_before_name.line, pos_after_name.line } }, move(arguments), move(syntax_error)); @@ -419,7 +419,7 @@ RefPtr<AST::Node> Parser::parse_function_decl() RefPtr<AST::SyntaxError> syntax_error; { auto cbrace_error_start = push_start(); - syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a function body", true); + syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end a function body"sv).release_value_but_fixme_should_propagate_errors(), true); } if (!expect('}')) { if (body) @@ -429,7 +429,7 @@ RefPtr<AST::Node> Parser::parse_function_decl() return create<AST::FunctionDeclaration>( AST::NameWithPosition { - move(function_name), + String::from_utf8(function_name).release_value_but_fixme_should_propagate_errors(), { pos_before_name.offset, pos_after_name.offset, pos_before_name.line, pos_after_name.line } }, move(arguments), move(body)); @@ -438,7 +438,7 @@ RefPtr<AST::Node> Parser::parse_function_decl() return create<AST::FunctionDeclaration>( AST::NameWithPosition { - move(function_name), + String::from_utf8(function_name).release_value_but_fixme_should_propagate_errors(), { pos_before_name.offset, pos_after_name.offset, pos_before_name.line, pos_after_name.line } }, move(arguments), move(body)); @@ -460,7 +460,7 @@ RefPtr<AST::Node> Parser::parse_or_logical_sequence() auto right_and_sequence = parse_and_logical_sequence(); if (!right_and_sequence) - right_and_sequence = create<AST::SyntaxError>("Expected an expression after '||'", true); + right_and_sequence = create<AST::SyntaxError>(String::from_utf8("Expected an expression after '||'"sv).release_value_but_fixme_should_propagate_errors(), true); return create<AST::Or>( and_sequence.release_nonnull(), @@ -484,7 +484,7 @@ RefPtr<AST::Node> Parser::parse_and_logical_sequence() auto right_and_sequence = parse_and_logical_sequence(); if (!right_and_sequence) - right_and_sequence = create<AST::SyntaxError>("Expected an expression after '&&'", true); + right_and_sequence = create<AST::SyntaxError>(String::from_utf8("Expected an expression after '&&'"sv).release_value_but_fixme_should_propagate_errors(), true); return create<AST::And>( pipe_sequence.release_nonnull(), @@ -642,7 +642,7 @@ RefPtr<AST::Node> Parser::parse_for_loop() auto offset_after_variable = current_position(); index_variable_name = AST::NameWithPosition { - variable, + String::from_utf8(variable).release_value_but_fixme_should_propagate_errors(), { offset_before_variable.offset, offset_after_variable.offset, offset_before_variable.line, offset_after_variable.line }, }; @@ -660,13 +660,13 @@ RefPtr<AST::Node> Parser::parse_for_loop() auto variable_name_end_offset = current_position(); if (!name.is_empty()) { variable_name = AST::NameWithPosition { - name, + String::from_utf8(name).release_value_but_fixme_should_propagate_errors(), { variable_name_start_offset.offset, variable_name_end_offset.offset, variable_name_start_offset.line, variable_name_end_offset.line } }; consume_while(is_whitespace); auto in_error_start = push_start(); if (!expect("in"sv)) { - auto syntax_error = create<AST::SyntaxError>("Expected 'in' after a variable name in a 'for' loop", true); + auto syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected 'in' after a variable name in a 'for' loop"sv).release_value_but_fixme_should_propagate_errors(), true); return create<AST::ForLoop>(move(variable_name), move(index_variable_name), move(syntax_error), nullptr); // ForLoop Var Iterated Block } in_start_position = AST::Position { in_error_start->offset, m_offset, in_error_start->line, line() }; @@ -678,14 +678,14 @@ RefPtr<AST::Node> Parser::parse_for_loop() auto iter_error_start = push_start(); iterated_expression = parse_expression(); if (!iterated_expression) - iterated_expression = create<AST::SyntaxError>("Expected an expression in 'for' loop", true); + iterated_expression = create<AST::SyntaxError>(String::from_utf8("Expected an expression in 'for' loop"sv).release_value_but_fixme_should_propagate_errors(), true); } consume_while(is_any_of(" \t\n"sv)); { auto obrace_error_start = push_start(); if (!expect('{')) { - auto syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a 'for' loop body", true); + auto syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected an open brace '{' to start a 'for' loop body"sv).release_value_but_fixme_should_propagate_errors(), true); return create<AST::ForLoop>(move(variable_name), move(index_variable_name), move(iterated_expression), move(syntax_error), move(in_start_position), move(index_start_position)); // ForLoop Var Iterated Block } } @@ -697,7 +697,7 @@ RefPtr<AST::Node> Parser::parse_for_loop() auto cbrace_error_start = push_start(); if (!expect('}')) { auto error_start = push_start(); - auto syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a 'for' loop body", true); + auto syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end a 'for' loop body"sv).release_value_but_fixme_should_propagate_errors(), true); if (body) body->set_is_syntax_error(*syntax_error); else @@ -722,7 +722,7 @@ RefPtr<AST::Node> Parser::parse_loop_loop() { auto obrace_error_start = push_start(); if (!expect('{')) { - auto syntax_error = create<AST::SyntaxError>("Expected an open brace '{' to start a 'loop' loop body", true); + auto syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected an open brace '{' to start a 'loop' loop body"sv).release_value_but_fixme_should_propagate_errors(), true); return create<AST::ForLoop>(AST::NameWithPosition {}, AST::NameWithPosition {}, nullptr, move(syntax_error)); // ForLoop null null Block } } @@ -734,7 +734,7 @@ RefPtr<AST::Node> Parser::parse_loop_loop() auto cbrace_error_start = push_start(); if (!expect('}')) { auto error_start = push_start(); - auto syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a 'loop' loop body", true); + auto syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end a 'loop' loop body"sv).release_value_but_fixme_should_propagate_errors(), true); if (body) body->set_is_syntax_error(*syntax_error); else @@ -761,7 +761,7 @@ RefPtr<AST::Node> Parser::parse_if_expr() auto cond_error_start = push_start(); condition = parse_or_logical_sequence(); if (!condition) - condition = create<AST::SyntaxError>("Expected a logical sequence after 'if'", true); + condition = create<AST::SyntaxError>(String::from_utf8("Expected a logical sequence after 'if'"sv).release_value_but_fixme_should_propagate_errors(), true); } auto parse_braced_toplevel = [&]() -> RefPtr<AST::Node> { @@ -769,7 +769,7 @@ RefPtr<AST::Node> Parser::parse_if_expr() { auto obrace_error_start = push_start(); if (!expect('{')) { - body = create<AST::SyntaxError>("Expected an open brace '{' to start an 'if' true branch", true); + body = create<AST::SyntaxError>(String::from_utf8("Expected an open brace '{' to start an 'if' true branch"sv).release_value_but_fixme_should_propagate_errors(), true); } } @@ -780,7 +780,7 @@ RefPtr<AST::Node> Parser::parse_if_expr() auto cbrace_error_start = push_start(); if (!expect('}')) { auto error_start = push_start(); - RefPtr<AST::SyntaxError> syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end an 'if' true branch", true); + RefPtr<AST::SyntaxError> syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end an 'if' true branch"sv).release_value_but_fixme_should_propagate_errors(), true); if (body) body->set_is_syntax_error(*syntax_error); else @@ -832,7 +832,7 @@ RefPtr<AST::Node> Parser::parse_subshell() auto cbrace_error_start = push_start(); if (!expect('}')) { auto error_start = push_start(); - RefPtr<AST::SyntaxError> syntax_error = create<AST::SyntaxError>("Expected a close brace '}' to end a subshell", true); + RefPtr<AST::SyntaxError> syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end a subshell"sv).release_value_but_fixme_should_propagate_errors(), true); if (body) body->set_is_syntax_error(*syntax_error); else @@ -857,13 +857,13 @@ RefPtr<AST::Node> Parser::parse_match_expr() auto match_expression = parse_expression(); if (!match_expression) { return create<AST::MatchExpr>( - create<AST::SyntaxError>("Expected an expression after 'match'", true), - DeprecatedString {}, Optional<AST::Position> {}, Vector<AST::MatchEntry> {}); + create<AST::SyntaxError>(String::from_utf8("Expected an expression after 'match'"sv).release_value_but_fixme_should_propagate_errors(), true), + String {}, Optional<AST::Position> {}, Vector<AST::MatchEntry> {}); } consume_while(is_any_of(" \t\n"sv)); - DeprecatedString match_name; + String match_name; Optional<AST::Position> as_position; auto as_start = m_offset; auto as_line = line(); @@ -873,17 +873,17 @@ RefPtr<AST::Node> Parser::parse_match_expr() if (consume_while(is_any_of(" \t\n"sv)).is_empty()) { auto node = create<AST::MatchExpr>( match_expression.release_nonnull(), - DeprecatedString {}, move(as_position), Vector<AST::MatchEntry> {}); - node->set_is_syntax_error(create<AST::SyntaxError>("Expected whitespace after 'as' in 'match'", true)); + String {}, move(as_position), Vector<AST::MatchEntry> {}); + node->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected whitespace after 'as' in 'match'"sv).release_value_but_fixme_should_propagate_errors(), true)); return node; } - match_name = consume_while(is_word_character); + match_name = String::from_utf8(consume_while(is_word_character)).release_value_but_fixme_should_propagate_errors(); if (match_name.is_empty()) { auto node = create<AST::MatchExpr>( match_expression.release_nonnull(), - DeprecatedString {}, move(as_position), Vector<AST::MatchEntry> {}); - node->set_is_syntax_error(create<AST::SyntaxError>("Expected an identifier after 'as' in 'match'", true)); + String {}, move(as_position), Vector<AST::MatchEntry> {}); + node->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected an identifier after 'as' in 'match'"sv).release_value_but_fixme_should_propagate_errors(), true)); return node; } } @@ -894,7 +894,7 @@ RefPtr<AST::Node> Parser::parse_match_expr() auto node = create<AST::MatchExpr>( match_expression.release_nonnull(), move(match_name), move(as_position), Vector<AST::MatchEntry> {}); - node->set_is_syntax_error(create<AST::SyntaxError>("Expected an open brace '{' to start a 'match' entry list", true)); + node->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected an open brace '{' to start a 'match' entry list"sv).release_value_but_fixme_should_propagate_errors(), true)); return node; } @@ -916,7 +916,7 @@ RefPtr<AST::Node> Parser::parse_match_expr() auto node = create<AST::MatchExpr>( match_expression.release_nonnull(), move(match_name), move(as_position), move(entries)); - node->set_is_syntax_error(create<AST::SyntaxError>("Expected a close brace '}' to end a 'match' entry list", true)); + node->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end a 'match' entry list"sv).release_value_but_fixme_should_propagate_errors(), true)); return node; } @@ -930,7 +930,7 @@ AST::MatchEntry Parser::parse_match_entry() NonnullRefPtrVector<AST::Node> patterns; Vector<Regex<ECMA262>> regexps; Vector<AST::Position> pipe_positions; - Optional<Vector<DeprecatedString>> match_names; + Optional<Vector<String>> match_names; Optional<AST::Position> match_as_position; enum { Regex, @@ -942,14 +942,14 @@ AST::MatchEntry Parser::parse_match_entry() auto regex_pattern = parse_regex_pattern(); if (regex_pattern.has_value()) { if (auto error = regex_pattern.value().parser_result.error; error != regex::Error::NoError) - return { NonnullRefPtrVector<AST::Node> {}, {}, {}, {}, create<AST::SyntaxError>(regex::get_error_string(error), false) }; + return { NonnullRefPtrVector<AST::Node> {}, {}, {}, {}, create<AST::SyntaxError>(String::from_utf8(regex::get_error_string(error)).release_value_but_fixme_should_propagate_errors(), false) }; pattern_kind = Regex; regexps.append(regex_pattern.release_value()); } else { auto glob_pattern = parse_match_pattern(); if (!glob_pattern) - return { NonnullRefPtrVector<AST::Node> {}, {}, {}, {}, create<AST::SyntaxError>("Expected a pattern in 'match' body", true) }; + return { NonnullRefPtrVector<AST::Node> {}, {}, {}, {}, create<AST::SyntaxError>(String::from_utf8("Expected a pattern in 'match' body"sv).release_value_but_fixme_should_propagate_errors(), true) }; pattern_kind = Glob; patterns.append(glob_pattern.release_nonnull()); @@ -967,7 +967,7 @@ AST::MatchEntry Parser::parse_match_entry() case Regex: { auto pattern = parse_regex_pattern(); if (!pattern.has_value()) { - error = create<AST::SyntaxError>("Expected a regex pattern to follow '|' in 'match' body", true); + error = create<AST::SyntaxError>(String::from_utf8("Expected a regex pattern to follow '|' in 'match' body"sv).release_value_but_fixme_should_propagate_errors(), true); break; } regexps.append(pattern.release_value()); @@ -976,7 +976,7 @@ AST::MatchEntry Parser::parse_match_entry() case Glob: { auto pattern = parse_match_pattern(); if (!pattern) { - error = create<AST::SyntaxError>("Expected a pattern to follow '|' in 'match' body", true); + error = create<AST::SyntaxError>(String::from_utf8("Expected a pattern to follow '|' in 'match' body"sv).release_value_but_fixme_should_propagate_errors(), true); break; } patterns.append(pattern.release_nonnull()); @@ -999,42 +999,42 @@ AST::MatchEntry Parser::parse_match_entry() consume_while(is_any_of(" \t\n"sv)); if (!expect('(')) { if (!error) - error = create<AST::SyntaxError>("Expected an explicit list of identifiers after a pattern 'as'"); + error = create<AST::SyntaxError>(String::from_utf8("Expected an explicit list of identifiers after a pattern 'as'"sv).release_value_but_fixme_should_propagate_errors()); } else { - match_names = Vector<DeprecatedString>(); + match_names = Vector<String>(); for (;;) { consume_while(is_whitespace); auto name = consume_while(is_word_character); if (name.is_empty()) break; - match_names.value().append(move(name)); + match_names->append(String::from_utf8(name).release_value_but_fixme_should_propagate_errors()); } if (!expect(')')) { if (!error) - error = create<AST::SyntaxError>("Expected a close paren ')' to end the identifier list of pattern 'as'", true); + error = create<AST::SyntaxError>(String::from_utf8("Expected a close paren ')' to end the identifier list of pattern 'as'"sv).release_value_but_fixme_should_propagate_errors(), true); } } consume_while(is_any_of(" \t\n"sv)); } if (pattern_kind == Regex) { - Vector<DeprecatedString> names; + Vector<String> names; for (auto& regex : regexps) { if (names.is_empty()) { for (auto& name : regex.parser_result.capture_groups) - names.append(name); + names.append(String::from_utf8(name).release_value_but_fixme_should_propagate_errors()); } else { size_t index = 0; for (auto& name : regex.parser_result.capture_groups) { if (names.size() <= index) { - names.append(name); + names.append(String::from_utf8(name).release_value_but_fixme_should_propagate_errors()); continue; } - if (names[index] != name) { + if (names[index] != name.view()) { if (!error) - error = create<AST::SyntaxError>("Alternative regex patterns must have the same capture groups", false); + error = create<AST::SyntaxError>(String::from_utf8("Alternative regex patterns must have the same capture groups"sv).release_value_but_fixme_should_propagate_errors(), false); break; } } @@ -1045,14 +1045,14 @@ AST::MatchEntry Parser::parse_match_entry() if (!expect('{')) { if (!error) - error = create<AST::SyntaxError>("Expected an open brace '{' to start a match entry body", true); + error = create<AST::SyntaxError>(String::from_utf8("Expected an open brace '{' to start a match entry body"sv).release_value_but_fixme_should_propagate_errors(), true); } auto body = parse_toplevel(); if (!expect('}')) { if (!error) - error = create<AST::SyntaxError>("Expected a close brace '}' to end a match entry body", true); + error = create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end a match entry body"sv).release_value_but_fixme_should_propagate_errors(), true); } if (body && error) @@ -1131,7 +1131,7 @@ RefPtr<AST::Node> Parser::parse_redirection() // Eat a character and hope the problem goes away consume(); } - path = create<AST::SyntaxError>("Expected a path after redirection", true); + path = create<AST::SyntaxError>(String::from_utf8("Expected a path after redirection"sv).release_value_but_fixme_should_propagate_errors(), true); } return create<AST::WriteAppendRedirection>(pipe_fd, path.release_nonnull()); // Redirection WriteAppend } @@ -1154,7 +1154,7 @@ RefPtr<AST::Node> Parser::parse_redirection() } auto redir = create<AST::Fd2FdRedirection>(pipe_fd, dest_pipe_fd); // Redirection Fd2Fd if (dest_pipe_fd == -1) - redir->set_is_syntax_error(*create<AST::SyntaxError>("Expected a file descriptor")); + redir->set_is_syntax_error(*create<AST::SyntaxError>(String::from_utf8("Expected a file descriptor"sv).release_value_but_fixme_should_propagate_errors())); return redir; } consume_while(is_whitespace); @@ -1165,7 +1165,7 @@ RefPtr<AST::Node> Parser::parse_redirection() // Eat a character and hope the problem goes away consume(); } - path = create<AST::SyntaxError>("Expected a path after redirection", true); + path = create<AST::SyntaxError>(String::from_utf8("Expected a path after redirection"sv).release_value_but_fixme_should_propagate_errors(), true); } return create<AST::WriteRedirection>(pipe_fd, path.release_nonnull()); // Redirection Write } @@ -1189,7 +1189,7 @@ RefPtr<AST::Node> Parser::parse_redirection() // Eat a character and hope the problem goes away consume(); } - path = create<AST::SyntaxError>("Expected a path after redirection", true); + path = create<AST::SyntaxError>(String::from_utf8("Expected a path after redirection"sv).release_value_but_fixme_should_propagate_errors(), true); } if (mode == Read) return create<AST::ReadRedirection>(pipe_fd, path.release_nonnull()); // Redirection Read @@ -1226,7 +1226,7 @@ RefPtr<AST::Node> Parser::parse_expression() { auto rule_start = push_start(); if (m_rule_start_offsets.size() > max_allowed_nested_rule_depth) - return create<AST::SyntaxError>(DeprecatedString::formatted("Expression nested too deep (max allowed is {})", max_allowed_nested_rule_depth)); + return create<AST::SyntaxError>(String::formatted("Expression nested too deep (max allowed is {})", max_allowed_nested_rule_depth).release_value_but_fixme_should_propagate_errors()); auto starting_char = peek(); @@ -1362,10 +1362,10 @@ RefPtr<AST::Node> Parser::parse_string() consume(); auto inner = parse_string_inner(StringEndCondition::DoubleQuote); if (!inner) - inner = create<AST::SyntaxError>("Unexpected EOF in string", true); + inner = create<AST::SyntaxError>(String::from_utf8("Unexpected EOF in string"sv).release_value_but_fixme_should_propagate_errors(), true); if (!expect('"')) { inner = create<AST::DoubleQuotedString>(move(inner)); - inner->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating double quote", true)); + inner->set_is_syntax_error(*create<AST::SyntaxError>(String::from_utf8("Expected a terminating double quote"sv).release_value_but_fixme_should_propagate_errors(), true)); return inner; } return create<AST::DoubleQuotedString>(move(inner)); // Double Quoted String @@ -1377,9 +1377,9 @@ RefPtr<AST::Node> Parser::parse_string() bool is_error = false; if (!expect('\'')) is_error = true; - auto result = create<AST::StringLiteral>(move(text), AST::StringLiteral::EnclosureType::SingleQuotes); // String Literal + auto result = create<AST::StringLiteral>(String::from_utf8(text).release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::SingleQuotes); // String Literal if (is_error) - result->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating single quote", true)); + result->set_is_syntax_error(*create<AST::SyntaxError>(String::from_utf8("Expected a terminating single quote"sv).release_value_but_fixme_should_propagate_errors(), true)); return result; } @@ -1459,7 +1459,7 @@ RefPtr<AST::Node> Parser::parse_string_inner(StringEndCondition condition) continue; } if (peek() == '$') { - auto string_literal = create<AST::StringLiteral>(builder.to_deprecated_string(), AST::StringLiteral::EnclosureType::DoubleQuotes); // String Literal + auto string_literal = create<AST::StringLiteral>(builder.to_string().release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::DoubleQuotes); // String Literal auto read_concat = [&](auto&& node) { auto inner = create<AST::StringPartCompose>( move(string_literal), @@ -1485,7 +1485,7 @@ RefPtr<AST::Node> Parser::parse_string_inner(StringEndCondition condition) builder.append(consume()); } - return create<AST::StringLiteral>(builder.to_deprecated_string(), AST::StringLiteral::EnclosureType::DoubleQuotes); // String Literal + return create<AST::StringLiteral>(builder.to_string().release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::DoubleQuotes); // String Literal } RefPtr<AST::Node> Parser::parse_variable() @@ -1530,7 +1530,7 @@ RefPtr<AST::Node> Parser::parse_variable_ref() return nullptr; } - return create<AST::SimpleVariable>(move(name)); // Variable Simple + return create<AST::SimpleVariable>(String::from_utf8(name).release_value_but_fixme_should_propagate_errors()); // Variable Simple } RefPtr<AST::Slice> Parser::parse_slice() @@ -1548,7 +1548,7 @@ RefPtr<AST::Slice> Parser::parse_slice() RefPtr<AST::SyntaxError> error; if (peek() != ']') - error = create<AST::SyntaxError>("Expected a close bracket ']' to end a variable slice"); + error = create<AST::SyntaxError>(String::from_utf8("Expected a close bracket ']' to end a variable slice"sv).release_value_but_fixme_should_propagate_errors()); else consume(); @@ -1556,7 +1556,7 @@ RefPtr<AST::Slice> Parser::parse_slice() if (error) spec = move(error); else - spec = create<AST::SyntaxError>("Expected either a range, or a comma-seprated list of selectors"); + spec = create<AST::SyntaxError>(String::from_utf8("Expected either a range, or a comma-seprated list of selectors"sv).release_value_but_fixme_should_propagate_errors()); } auto node = create<AST::Slice>(spec.release_nonnull()); @@ -1579,16 +1579,16 @@ RefPtr<AST::Node> Parser::parse_evaluate() consume(); auto inner = parse_pipe_sequence(); if (!inner) - inner = create<AST::SyntaxError>("Unexpected EOF in list", true); + inner = create<AST::SyntaxError>(String::from_utf8("Unexpected EOF in list"sv).release_value_but_fixme_should_propagate_errors(), true); if (!expect(')')) - inner->set_is_syntax_error(*create<AST::SyntaxError>("Expected a terminating close paren", true)); + inner->set_is_syntax_error(*create<AST::SyntaxError>(String::from_utf8("Expected a terminating close paren"sv).release_value_but_fixme_should_propagate_errors(), true)); return create<AST::Execute>(inner.release_nonnull(), true); } auto inner = parse_expression(); if (!inner) { - inner = create<AST::SyntaxError>("Expected a command", true); + inner = create<AST::SyntaxError>(String::from_utf8("Expected a command"sv).release_value_but_fixme_should_propagate_errors(), true); } else { if (inner->is_list()) { auto execute_inner = create<AST::Execute>(inner.release_nonnull(), true); @@ -1659,14 +1659,14 @@ RefPtr<AST::Node> Parser::parse_immediate_expression() }; auto node = create<AST::ImmediateExpression>( - AST::NameWithPosition { function_name, move(function_position) }, + AST::NameWithPosition { String::from_utf8(function_name).release_value_but_fixme_should_propagate_errors(), move(function_position) }, move(arguments), ending_brace_position); if (!ending_brace_position.has_value()) - node->set_is_syntax_error(create<AST::SyntaxError>("Expected a closing brace '}' to end an immediate expression", true)); + node->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected a closing brace '}' to end an immediate expression"sv).release_value_but_fixme_should_propagate_errors(), true)); else if (node->function_name().is_empty()) - node->set_is_syntax_error(create<AST::SyntaxError>("Expected an immediate function name")); + node->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected an immediate function name"sv).release_value_but_fixme_should_propagate_errors())); return node; } @@ -1711,7 +1711,7 @@ RefPtr<AST::Node> Parser::parse_history_designator() consume(); selector.event.kind = AST::HistorySelector::EventKind::IndexFromEnd; selector.event.index = 0; - selector.event.text = "!"; + selector.event.text = String::from_utf8_short_string("!"sv); break; case '?': consume(); @@ -1728,22 +1728,23 @@ RefPtr<AST::Node> Parser::parse_history_designator() selector.event.text = static_ptr_cast<AST::BarewordLiteral>(bareword)->text(); selector.event.text_position = bareword->position(); - auto it = selector.event.text.begin(); + auto selector_bytes = selector.event.text.bytes(); + auto it = selector_bytes.begin(); bool is_negative = false; if (*it == '-') { ++it; is_negative = true; } - if (it != selector.event.text.end() && all_of(it, selector.event.text.end(), is_digit)) { + if (it != selector_bytes.end() && all_of(it, selector_bytes.end(), is_digit)) { if (is_negative) selector.event.kind = AST::HistorySelector::EventKind::IndexFromEnd; else selector.event.kind = AST::HistorySelector::EventKind::IndexFromStart; - auto number = abs(selector.event.text.to_int().value_or(0)); + auto number = abs(selector.event.text.bytes_as_string_view().to_int().value_or(0)); if (number != 0) selector.event.index = number - 1; else - syntax_error = create<AST::SyntaxError>("History entry index value invalid or out of range"); + syntax_error = create<AST::SyntaxError>(String::from_utf8("History entry index value invalid or out of range"sv).release_value_but_fixme_should_propagate_errors()); } if (":^$*"sv.contains(peek())) { is_word_selector = true; @@ -1803,7 +1804,7 @@ RefPtr<AST::Node> Parser::parse_history_designator() auto first_char = peek(); if (!(is_digit(first_char) || "^$-*"sv.contains(first_char))) { if (!syntax_error) - syntax_error = create<AST::SyntaxError>("Expected a word selector after ':' in a history event designator", true); + syntax_error = create<AST::SyntaxError>(String::from_utf8("Expected a word selector after ':' in a history event designator"sv).release_value_but_fixme_should_propagate_errors(), true); } else if (first_char == '*') { consume(); selector.word_selector_range.start = make_word_selector(AST::HistorySelector::WordSelectorKind::Index, 1); @@ -1853,7 +1854,7 @@ RefPtr<AST::Node> Parser::parse_comment() consume(); auto text = consume_while(is_not('\n')); - return create<AST::Comment>(move(text)); // Comment + return create<AST::Comment>(String::from_utf8(text).release_value_but_fixme_should_propagate_errors()); // Comment } RefPtr<AST::Node> Parser::parse_bareword() @@ -1895,18 +1896,18 @@ RefPtr<AST::Node> Parser::parse_bareword() auto current_end = m_offset; auto current_line = line(); - auto string = builder.to_deprecated_string(); + auto string = builder.to_string().release_value_but_fixme_should_propagate_errors(); if (string.starts_with('~')) { - DeprecatedString username; + String username; RefPtr<AST::Node> tilde, text; - auto first_slash_index = string.find('/'); + auto first_slash_index = string.find_byte_offset('/'); if (first_slash_index.has_value()) { - username = string.substring_view(1, first_slash_index.value() - 1); - string = string.substring_view(first_slash_index.value(), string.length() - first_slash_index.value()); + username = string.substring_from_byte_offset(1, *first_slash_index).release_value_but_fixme_should_propagate_errors(); + string = string.substring_from_byte_offset(*first_slash_index + 1).release_value_but_fixme_should_propagate_errors(); } else { - username = string.substring_view(1, string.length() - 1); - string = ""; + username = string.substring_from_byte_offset(1).release_value_but_fixme_should_propagate_errors(); + string = {}; } // Synthesize a Tilde Node with the correct positioning information. @@ -1914,7 +1915,7 @@ RefPtr<AST::Node> Parser::parse_bareword() restore_to(rule_start->offset, rule_start->line); auto ch = consume(); VERIFY(ch == '~'); - auto username_length = username.length(); + auto username_length = username.bytes_as_string_view().length(); tilde = create<AST::Tilde>(move(username)); // Consume the username (if any) for (size_t i = 0; i < username_length; ++i) @@ -1934,9 +1935,9 @@ RefPtr<AST::Node> Parser::parse_bareword() return create<AST::Juxtaposition>(tilde.release_nonnull(), text.release_nonnull()); // Juxtaposition Variable Bareword } - if (string.starts_with("\\~"sv)) { + if (string.starts_with_bytes("\\~"sv)) { // Un-escape the tilde, but only at the start (where it would be an expansion) - string = string.substring(1, string.length() - 1); + string = string.substring_from_byte_offset(1).release_value_but_fixme_should_propagate_errors(); } return create<AST::BarewordLiteral>(move(string)); // Bareword Literal @@ -1963,7 +1964,7 @@ RefPtr<AST::Node> Parser::parse_glob() } else { // FIXME: Allow composition of tilde+bareword with globs: '~/foo/bar/baz*' restore_to(saved_offset.offset, saved_offset.line); - bareword_part->set_is_syntax_error(*create<AST::SyntaxError>(DeprecatedString::formatted("Unexpected {} inside a glob", bareword_part->class_name()))); + bareword_part->set_is_syntax_error(*create<AST::SyntaxError>(String::formatted("Unexpected {} inside a glob", bareword_part->class_name()).release_value_but_fixme_should_propagate_errors())); return bareword_part; } textbuilder.append(text); @@ -1984,11 +1985,11 @@ RefPtr<AST::Node> Parser::parse_glob() textbuilder.append('~'); textbuilder.append(bareword->text()); } else { - return create<AST::SyntaxError>(DeprecatedString::formatted("Invalid node '{}' in glob position, escape shell special characters", glob_after->class_name())); + return create<AST::SyntaxError>(String::formatted("Invalid node '{}' in glob position, escape shell special characters", glob_after->class_name()).release_value_but_fixme_should_propagate_errors()); } } - return create<AST::Glob>(textbuilder.to_deprecated_string()); // Glob + return create<AST::Glob>(textbuilder.to_string().release_value_but_fixme_should_propagate_errors()); // Glob } return bareword_part; @@ -2003,7 +2004,7 @@ RefPtr<AST::Node> Parser::parse_brace_expansion() if (auto spec = parse_brace_expansion_spec()) { if (!expect('}')) - spec->set_is_syntax_error(create<AST::SyntaxError>("Expected a close brace '}' to end a brace expansion", true)); + spec->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected a close brace '}' to end a brace expansion"sv).release_value_but_fixme_should_propagate_errors(), true)); return spec; } @@ -2024,19 +2025,19 @@ RefPtr<AST::Node> Parser::parse_brace_expansion_spec() if (next_is(","sv)) { // Note that we don't consume the ',' here. - subexpressions.append(create<AST::StringLiteral>("", AST::StringLiteral::EnclosureType::None)); + subexpressions.append(create<AST::StringLiteral>(String {}, AST::StringLiteral::EnclosureType::None)); } else { auto start_expr = parse_expression(); if (start_expr) { if (expect(".."sv)) { if (auto end_expr = parse_expression()) { if (end_expr->position().start_offset != start_expr->position().end_offset + 2) - end_expr->set_is_syntax_error(create<AST::SyntaxError>("Expected no whitespace between '..' and the following expression in brace expansion")); + end_expr->set_is_syntax_error(create<AST::SyntaxError>(String::from_utf8("Expected no whitespace between '..' and the following expression in brace expansion"sv).release_value_but_fixme_should_propagate_errors())); return create<AST::Range>(start_expr.release_nonnull(), end_expr.release_nonnull()); } - return create<AST::Range>(start_expr.release_nonnull(), create<AST::SyntaxError>("Expected an expression to end range brace expansion with", true)); + return create<AST::Range>(start_expr.release_nonnull(), create<AST::SyntaxError>(String::from_utf8("Expected an expression to end range brace expansion with"sv).release_value_but_fixme_should_propagate_errors(), true)); } } @@ -2049,7 +2050,7 @@ RefPtr<AST::Node> Parser::parse_brace_expansion_spec() if (expr) { subexpressions.append(expr.release_nonnull()); } else { - subexpressions.append(create<AST::StringLiteral>("", AST::StringLiteral::EnclosureType::None)); + subexpressions.append(create<AST::StringLiteral>(String {}, AST::StringLiteral::EnclosureType::None)); } } @@ -2071,7 +2072,7 @@ RefPtr<AST::Node> Parser::parse_heredoc_initiation_record() consume(); HeredocInitiationRecord record; - record.end = "<error>"; + record.end = String::from_utf8("<error>"sv).release_value_but_fixme_should_propagate_errors(); RefPtr<AST::SyntaxError> syntax_error_node; @@ -2093,7 +2094,7 @@ RefPtr<AST::Node> Parser::parse_heredoc_initiation_record() // StringLiteral | bareword if (auto bareword = parse_bareword()) { if (!bareword->is_bareword()) { - syntax_error_node = create<AST::SyntaxError>(DeprecatedString::formatted("Expected a bareword or a quoted string, not {}", bareword->class_name())); + syntax_error_node = create<AST::SyntaxError>(String::formatted("Expected a bareword or a quoted string, not {}", bareword->class_name()).release_value_but_fixme_should_propagate_errors()); } else { if (bareword->is_syntax_error()) syntax_error_node = bareword->syntax_error_node(); @@ -2109,19 +2110,19 @@ RefPtr<AST::Node> Parser::parse_heredoc_initiation_record() if (!expect('\'')) is_error = true; if (is_error) - syntax_error_node = create<AST::SyntaxError>("Expected a terminating single quote", true); + syntax_error_node = create<AST::SyntaxError>(String::from_utf8("Expected a terminating single quote"sv).release_value_but_fixme_should_propagate_errors(), true); - record.end = text; + record.end = String::from_utf8(text).release_value_but_fixme_should_propagate_errors(); record.interpolate = false; } else { - syntax_error_node = create<AST::SyntaxError>("Expected a bareword or a single-quoted string literal for heredoc end key", true); + syntax_error_node = create<AST::SyntaxError>(String::from_utf8("Expected a bareword or a single-quoted string literal for heredoc end key"sv).release_value_but_fixme_should_propagate_errors(), true); } auto node = create<AST::Heredoc>(record.end, record.interpolate, record.deindent); if (syntax_error_node) node->set_is_syntax_error(*syntax_error_node); else - node->set_is_syntax_error(*create<AST::SyntaxError>(DeprecatedString::formatted("Expected heredoc contents for heredoc with end key '{}'", node->end()), true)); + node->set_is_syntax_error(*create<AST::SyntaxError>(String::formatted("Expected heredoc contents for heredoc with end key '{}'", node->end()).release_value_but_fixme_should_propagate_errors(), true)); record.node = node; m_heredoc_initiations.append(move(record)); @@ -2137,7 +2138,7 @@ bool Parser::parse_heredoc_entries() for (auto& record : heredocs) { auto rule_start = push_start(); if (m_rule_start_offsets.size() > max_allowed_nested_rule_depth) { - record.node->set_is_syntax_error(*create<AST::SyntaxError>(DeprecatedString::formatted("Expression nested too deep (max allowed is {})", max_allowed_nested_rule_depth))); + record.node->set_is_syntax_error(*create<AST::SyntaxError>(String::formatted("Expression nested too deep (max allowed is {})", max_allowed_nested_rule_depth).release_value_but_fixme_should_propagate_errors())); continue; } bool found_key = false; @@ -2162,9 +2163,11 @@ bool Parser::parse_heredoc_entries() if (!last_line_offset.has_value()) last_line_offset = current_position(); // Now just wrap it in a StringLiteral and set it as the node's contents - auto node = create<AST::StringLiteral>(m_input.substring_view(rule_start->offset, last_line_offset->offset - rule_start->offset), AST::StringLiteral::EnclosureType::None); + auto node = create<AST::StringLiteral>( + String::from_utf8(m_input.substring_view(rule_start->offset, last_line_offset->offset - rule_start->offset)).release_value_but_fixme_should_propagate_errors(), + AST::StringLiteral::EnclosureType::None); if (!found_key) - node->set_is_syntax_error(*create<AST::SyntaxError>(DeprecatedString::formatted("Expected to find the heredoc key '{}', but found Eof", record.end), true)); + node->set_is_syntax_error(*create<AST::SyntaxError>(String::formatted("Expected to find the heredoc key '{}', but found Eof", record.end).release_value_but_fixme_should_propagate_errors(), true)); record.node->set_contents(move(node)); } else { // Interpolation is allowed, so we're going to read doublequoted string innards @@ -2211,11 +2214,11 @@ bool Parser::parse_heredoc_entries() } if (!expr && found_key) { - expr = create<AST::StringLiteral>("", AST::StringLiteral::EnclosureType::None); + expr = create<AST::StringLiteral>(String {}, AST::StringLiteral::EnclosureType::None); } else if (!expr) { - expr = create<AST::SyntaxError>(DeprecatedString::formatted("Expected to find a valid string inside a heredoc (with end key '{}')", record.end), true); + expr = create<AST::SyntaxError>(String::formatted("Expected to find a valid string inside a heredoc (with end key '{}')", record.end).release_value_but_fixme_should_propagate_errors(), true); } else if (!found_key) { - expr->set_is_syntax_error(*create<AST::SyntaxError>(DeprecatedString::formatted("Expected to find the heredoc key '{}'", record.end), true)); + expr->set_is_syntax_error(*create<AST::SyntaxError>(String::formatted("Expected to find the heredoc key '{}'", record.end).release_value_but_fixme_should_propagate_errors(), true)); } record.node->set_contents(create<AST::DoubleQuotedString>(move(expr))); diff --git a/Userland/Shell/Parser.h b/Userland/Shell/Parser.h index 91da805da4..802489d9b0 100644 --- a/Userland/Shell/Parser.h +++ b/Userland/Shell/Parser.h @@ -7,9 +7,9 @@ #pragma once #include "AST.h" -#include <AK/DeprecatedString.h> #include <AK/Function.h> #include <AK/RefPtr.h> +#include <AK/String.h> #include <AK/StringBuilder.h> #include <AK/Vector.h> @@ -53,7 +53,7 @@ private: }; struct HeredocInitiationRecord { - DeprecatedString end; + String end; RefPtr<AST::Heredoc> node; bool interpolate { false }; bool deindent { false }; diff --git a/Userland/Shell/PosixParser.cpp b/Userland/Shell/PosixParser.cpp index 427971c74e..fea91a5b95 100644 --- a/Userland/Shell/PosixParser.cpp +++ b/Userland/Shell/PosixParser.cpp @@ -149,7 +149,7 @@ void Parser::handle_heredoc_contents() Parser parser { token.value, m_in_interactive_mode, Reduction::HeredocContents }; contents = parser.parse_word(); } else { - contents = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), token.value, AST::StringLiteral::EnclosureType::None); + contents = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), String::from_utf8(token.value).release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::None); } if (contents) @@ -643,7 +643,7 @@ RefPtr<AST::Node> Parser::parse_complete_command() auto position = peek().position; auto syntax_error = make_ref_counted<AST::SyntaxError>( position.value_or(empty_position()), - "Extra tokens after complete command"sv); + String::from_utf8("Extra tokens after complete command"sv).release_value_but_fixme_should_propagate_errors()); if (list) list->set_is_syntax_error(*syntax_error); @@ -837,7 +837,7 @@ RefPtr<AST::Node> Parser::parse_function_definition() return make_ref_counted<AST::FunctionDeclaration>( name.position.value_or(empty_position()).with_end(peek().position.value_or(empty_position())), - AST::NameWithPosition { name.value, name.position.value_or(empty_position()) }, + AST::NameWithPosition { String::from_utf8(name.value).release_value_but_fixme_should_propagate_errors(), name.position.value_or(empty_position()) }, Vector<AST::NameWithPosition> {}, body.release_nonnull()); } @@ -921,13 +921,13 @@ RefPtr<AST::Node> Parser::parse_while_clause() if (!condition) condition = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - "Expected condition after 'while'"sv); + String::from_utf8("Expected condition after 'while'"sv).release_value_but_fixme_should_propagate_errors()); auto do_group = parse_do_group(); if (!do_group) do_group = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - "Expected 'do' after 'while'"sv); + String::from_utf8("Expected 'do' after 'while'"sv).release_value_but_fixme_should_propagate_errors()); // while foo; bar -> loop { if foo { bar } else { break } } return make_ref_counted<AST::ForLoop>( @@ -955,13 +955,13 @@ RefPtr<AST::Node> Parser::parse_until_clause() if (!condition) condition = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - "Expected condition after 'until'"sv); + String::from_utf8("Expected condition after 'until'"sv).release_value_but_fixme_should_propagate_errors()); auto do_group = parse_do_group(); if (!do_group) do_group = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - "Expected 'do' after 'until'"sv); + String::from_utf8("Expected 'do' after 'until'"sv).release_value_but_fixme_should_propagate_errors()); // until foo; bar -> loop { if foo { break } else { bar } } return make_ref_counted<AST::ForLoop>( @@ -992,7 +992,7 @@ RefPtr<AST::Node> Parser::parse_brace_group() if (peek().type != Token::Type::CloseBrace) { error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected '}}', not {}", peek().type_name())); + String::formatted("Expected '}}', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } else { consume(); } @@ -1020,12 +1020,12 @@ RefPtr<AST::Node> Parser::parse_case_clause() if (!expr) expr = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected a word, not {}", peek().type_name())); + String::formatted("Expected a word, not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); if (peek().type != Token::Type::In) { syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'in', not {}", peek().type_name())); + String::formatted("Expected 'in', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } else { skip(); } @@ -1059,7 +1059,7 @@ RefPtr<AST::Node> Parser::parse_case_clause() if (!syntax_error) syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected ')', not {}", peek().type_name())); + String::formatted("Expected ')', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); break; } @@ -1074,7 +1074,7 @@ RefPtr<AST::Node> Parser::parse_case_clause() if (!syntax_error) syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected ';;', not {}", peek().type_name())); + String::formatted("Expected ';;', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } if (syntax_error) { @@ -1097,7 +1097,7 @@ RefPtr<AST::Node> Parser::parse_case_clause() if (peek().type != Token::Type::Esac) { syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'esac', not {}", peek().type_name())); + String::formatted("Expected 'esac', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } else { skip(); } @@ -1105,7 +1105,7 @@ RefPtr<AST::Node> Parser::parse_case_clause() auto node = make_ref_counted<AST::MatchExpr>( start_position.with_end(peek().position.value_or(empty_position())), expr.release_nonnull(), - DeprecatedString {}, + String {}, Optional<AST::Position> {}, move(entries)); @@ -1132,7 +1132,7 @@ Parser::CaseItemsResult Parser::parse_case_list() if (!node) node = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected a word, not {}", peek().type_name())); + String::formatted("Expected a word, not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); nodes.append(node.release_nonnull()); @@ -1147,7 +1147,7 @@ Parser::CaseItemsResult Parser::parse_case_list() if (nodes.is_empty()) nodes.append(make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected a word, not {}", peek().type_name()))); + String::formatted("Expected a word, not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors())); return { move(pipes), move(nodes) }; } @@ -1162,20 +1162,20 @@ RefPtr<AST::Node> Parser::parse_if_clause() skip(); auto main_condition = parse_compound_list(); if (!main_condition) - main_condition = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'if'"); + main_condition = make_ref_counted<AST::SyntaxError>(empty_position(), String::from_utf8("Expected compound list after 'if'"sv).release_value_but_fixme_should_propagate_errors()); RefPtr<AST::SyntaxError> syntax_error; if (peek().type != Token::Type::Then) { syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'then', not {}", peek().type_name())); + String::formatted("Expected 'then', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } else { skip(); } auto main_consequence = parse_compound_list(); if (!main_consequence) - main_consequence = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'then'"); + main_consequence = make_ref_counted<AST::SyntaxError>(empty_position(), String::from_utf8("Expected compound list after 'then'"sv).release_value_but_fixme_should_propagate_errors()); auto node = make_ref_counted<AST::IfCond>(start_position, Optional<AST::Position>(), main_condition.release_nonnull(), main_consequence.release_nonnull(), nullptr); auto active_node = node; @@ -1184,20 +1184,20 @@ RefPtr<AST::Node> Parser::parse_if_clause() skip(); auto condition = parse_compound_list(); if (!condition) - condition = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'elif'"); + condition = make_ref_counted<AST::SyntaxError>(empty_position(), String::from_utf8("Expected compound list after 'elif'"sv).release_value_but_fixme_should_propagate_errors()); if (peek().type != Token::Type::Then) { if (!syntax_error) syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'then', not {}", peek().type_name())); + String::formatted("Expected 'then', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } else { skip(); } auto consequence = parse_compound_list(); if (!consequence) - consequence = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'then'"); + consequence = make_ref_counted<AST::SyntaxError>(empty_position(), String::from_utf8("Expected compound list after 'then'"sv).release_value_but_fixme_should_propagate_errors()); auto new_node = make_ref_counted<AST::IfCond>(start_position, Optional<AST::Position>(), condition.release_nonnull(), consequence.release_nonnull(), nullptr); @@ -1211,7 +1211,7 @@ RefPtr<AST::Node> Parser::parse_if_clause() skip(); active_node->false_branch() = parse_compound_list(); if (!active_node->false_branch()) - active_node->false_branch() = make_ref_counted<AST::SyntaxError>(empty_position(), "Expected compound list after 'else'"); + active_node->false_branch() = make_ref_counted<AST::SyntaxError>(empty_position(), String::from_utf8("Expected compound list after 'else'"sv).release_value_but_fixme_should_propagate_errors()); break; case Token::Type::Fi: needs_fi = false; @@ -1220,7 +1220,7 @@ RefPtr<AST::Node> Parser::parse_if_clause() if (!syntax_error) syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'else' or 'fi', not {}", peek().type_name())); + String::formatted("Expected 'else' or 'fi', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); break; } @@ -1229,7 +1229,7 @@ RefPtr<AST::Node> Parser::parse_if_clause() if (!syntax_error) syntax_error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'fi', not {}", peek().type_name())); + String::formatted("Expected 'fi', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } else { skip(); } @@ -1252,10 +1252,10 @@ RefPtr<AST::Node> Parser::parse_subshell() auto list = parse_compound_list(); if (!list) - error = make_ref_counted<AST::SyntaxError>(peek().position.value_or(empty_position()), "Expected compound list after ("sv); + error = make_ref_counted<AST::SyntaxError>(peek().position.value_or(empty_position()), String::from_utf8("Expected compound list after ("sv).release_value_but_fixme_should_propagate_errors()); if (peek().type != Token::Type::CloseParen) - error = make_ref_counted<AST::SyntaxError>(peek().position.value_or(empty_position()), "Expected ) after compound list"sv); + error = make_ref_counted<AST::SyntaxError>(peek().position.value_or(empty_position()), String::from_utf8("Expected ) after compound list"sv).release_value_but_fixme_should_propagate_errors()); else skip(); @@ -1369,7 +1369,7 @@ RefPtr<AST::Node> Parser::parse_for_clause() auto body = parse_do_group(); return AST::make_ref_counted<AST::ForLoop>( start_position.with_end(peek().position.value_or(empty_position())), - AST::NameWithPosition { move(name), name_position.value_or(empty_position()) }, + AST::NameWithPosition { String::from_deprecated_string(name).release_value_but_fixme_should_propagate_errors(), name_position.value_or(empty_position()) }, Optional<AST::NameWithPosition> {}, move(iterated_expression), move(body), @@ -1414,13 +1414,13 @@ RefPtr<AST::Node> Parser::parse_word() auto user = lexer.consume_while(is_ascii_alphanumeric); string = lexer.remaining(); - word = make_ref_counted<AST::Tilde>(token.position.value_or(empty_position()), user); + word = make_ref_counted<AST::Tilde>(token.position.value_or(empty_position()), String::from_utf8(user).release_value_but_fixme_should_propagate_errors()); } if (string.is_empty()) return; - auto node = make_ref_counted<AST::BarewordLiteral>(token.position.value_or(empty_position()), string); + auto node = make_ref_counted<AST::BarewordLiteral>(token.position.value_or(empty_position()), String::from_utf8(string).release_value_but_fixme_should_propagate_errors()); if (word) { word = make_ref_counted<AST::Juxtaposition>( @@ -1437,7 +1437,7 @@ RefPtr<AST::Node> Parser::parse_word() if (string.is_empty()) return; - auto node = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), string, AST::StringLiteral::EnclosureType::SingleQuotes); + auto node = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), String::from_utf8(string).release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::SingleQuotes); if (word) { word = make_ref_counted<AST::Juxtaposition>( @@ -1454,7 +1454,7 @@ RefPtr<AST::Node> Parser::parse_word() if (string.is_empty()) return; - auto node = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), string, AST::StringLiteral::EnclosureType::DoubleQuotes); + auto node = make_ref_counted<AST::StringLiteral>(token.position.value_or(empty_position()), String::from_utf8(string).release_value_but_fixme_should_propagate_errors(), AST::StringLiteral::EnclosureType::DoubleQuotes); if (word) { word = make_ref_counted<AST::Juxtaposition>( @@ -1512,12 +1512,12 @@ RefPtr<AST::Node> Parser::parse_word() case ResolvedParameterExpansion::Op::GetVariable: node = make_ref_counted<AST::SimpleVariable>( token.position.value_or(empty_position()), - x.parameter); + String::from_deprecated_string(x.parameter).release_value_but_fixme_should_propagate_errors()); break; case ResolvedParameterExpansion::Op::GetLastBackgroundPid: node = make_ref_counted<AST::SyntaxError>( token.position.value_or(empty_position()), - "$! not implemented"); + String::from_utf8("$! not implemented"sv).release_value_but_fixme_should_propagate_errors()); break; case ResolvedParameterExpansion::Op::GetPositionalParameterList: node = make_ref_counted<AST::SpecialVariable>( @@ -1527,7 +1527,7 @@ RefPtr<AST::Node> Parser::parse_word() case ResolvedParameterExpansion::Op::GetCurrentOptionFlags: node = make_ref_counted<AST::SyntaxError>( token.position.value_or(empty_position()), - "The current option flags are not available in parameter expansions"); + String::from_utf8("The current option flags are not available in parameter expansions"sv).release_value_but_fixme_should_propagate_errors()); break; case ResolvedParameterExpansion::Op::GetPositionalParameterCount: node = make_ref_counted<AST::SpecialVariable>( @@ -1542,7 +1542,7 @@ RefPtr<AST::Node> Parser::parse_word() case ResolvedParameterExpansion::Op::GetPositionalParameterListAsString: node = make_ref_counted<AST::SyntaxError>( token.position.value_or(empty_position()), - "$* not implemented"); + String::from_utf8("$* not implemented"sv).release_value_but_fixme_should_propagate_errors()); break; case ResolvedParameterExpansion::Op::GetShellProcessId: node = make_ref_counted<AST::SpecialVariable>( @@ -1555,7 +1555,7 @@ RefPtr<AST::Node> Parser::parse_word() NonnullRefPtrVector<AST::Node> arguments; arguments.append(make_ref_counted<AST::BarewordLiteral>( token.position.value_or(empty_position()), - x.parameter)); + String::from_deprecated_string(x.parameter).release_value_but_fixme_should_propagate_errors())); if (!x.argument.is_empty()) { // dbgln("Will parse {}", x.argument); @@ -1565,7 +1565,7 @@ RefPtr<AST::Node> Parser::parse_word() node = make_ref_counted<AST::ImmediateExpression>( token.position.value_or(empty_position()), AST::NameWithPosition { - immediate_function_name, + String::from_deprecated_string(immediate_function_name).release_value_but_fixme_should_propagate_errors(), token.position.value_or(empty_position()), }, move(arguments), @@ -1576,7 +1576,7 @@ RefPtr<AST::Node> Parser::parse_word() node = make_ref_counted<AST::ImmediateExpression>( token.position.value_or(empty_position()), AST::NameWithPosition { - "reexpand", + String::from_utf8("reexpand"sv).release_value_but_fixme_should_propagate_errors(), token.position.value_or(empty_position()), }, Vector { node.release_nonnull() }, @@ -1732,7 +1732,7 @@ RefPtr<AST::Node> Parser::parse_do_group() if (peek().type != Token::Type::Do) { return make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'do', not {}", peek().type_name())); + String::formatted("Expected 'do', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } consume(); @@ -1743,7 +1743,7 @@ RefPtr<AST::Node> Parser::parse_do_group() if (peek().type != Token::Type::Done) { error = make_ref_counted<AST::SyntaxError>( peek().position.value_or(empty_position()), - DeprecatedString::formatted("Expected 'done', not {}", peek().type_name())); + String::formatted("Expected 'done', not {}", peek().type_name()).release_value_but_fixme_should_propagate_errors()); } else { consume(); } @@ -1779,17 +1779,17 @@ RefPtr<AST::Node> Parser::parse_simple_command() nodes.append( make_ref_counted<AST::BarewordLiteral>( peek().position.value_or(empty_position()), - consume().value)); + String::from_deprecated_string(consume().value).release_value_but_fixme_should_propagate_errors())); } else { // env (assignments) (command) nodes.append(make_ref_counted<AST::BarewordLiteral>( empty_position(), - "env")); + String::from_utf8_short_string("env"sv))); nodes.append( make_ref_counted<AST::BarewordLiteral>( peek().position.value_or(empty_position()), - consume().value)); + String::from_deprecated_string(consume().value).release_value_but_fixme_should_propagate_errors())); } } @@ -1804,10 +1804,10 @@ RefPtr<AST::Node> Parser::parse_simple_command() auto parts = definition.split_limit('=', 2, SplitBehavior::KeepEmpty); auto name = make_ref_counted<AST::BarewordLiteral>( empty_position(), - parts[0]); + String::from_deprecated_string(parts[0]).release_value_but_fixme_should_propagate_errors()); auto value = make_ref_counted<AST::BarewordLiteral>( empty_position(), - parts.size() > 1 ? parts[1] : ""); + String::from_deprecated_string(parts.size() > 1 ? parts[1] : "").release_value_but_fixme_should_propagate_errors()); variables.append({ move(name), move(value) }); } @@ -1885,7 +1885,7 @@ RefPtr<AST::Node> Parser::parse_io_here(AST::Position start_position, Optional<i auto end_keyword = consume(); if (!is_one_of(end_keyword.type, Token::Type::Word, Token::Type::Token)) - return make_ref_counted<AST::SyntaxError>(io_operator_token.position.value_or(start_position), "Expected a heredoc keyword", true); + return make_ref_counted<AST::SyntaxError>(io_operator_token.position.value_or(start_position), String::from_utf8("Expected a heredoc keyword"sv).release_value_but_fixme_should_propagate_errors(), true); auto [end_keyword_text, allow_interpolation] = Lexer::process_heredoc_key(end_keyword); RefPtr<AST::SyntaxError> error; @@ -1893,7 +1893,7 @@ RefPtr<AST::Node> Parser::parse_io_here(AST::Position start_position, Optional<i auto position = start_position.with_end(peek().position.value_or(empty_position())); auto result = make_ref_counted<AST::Heredoc>( position, - end_keyword_text, + String::from_deprecated_string(end_keyword_text).release_value_but_fixme_should_propagate_errors(), allow_interpolation, io_operator == Token::Type::DoubleLessDash, Optional<int> { redirection_fd }); @@ -1954,7 +1954,7 @@ RefPtr<AST::Node> Parser::parse_io_file(AST::Position start_position, Optional<i auto is_less = io_operator == Token::Type::LessAnd; auto source_fd = fd.value_or(is_less ? 0 : 1); if (word->is_bareword()) { - auto maybe_target_fd = static_ptr_cast<AST::BarewordLiteral>(word)->text().to_int(AK::TrimWhitespace::No); + auto maybe_target_fd = static_ptr_cast<AST::BarewordLiteral>(word)->text().bytes_as_string_view().to_int(); if (maybe_target_fd.has_value()) { auto target_fd = maybe_target_fd.release_value(); if (is_less) diff --git a/Userland/Shell/Shell.cpp b/Userland/Shell/Shell.cpp index ef1e94ac93..5d288a34be 100644 --- a/Userland/Shell/Shell.cpp +++ b/Userland/Shell/Shell.cpp @@ -309,7 +309,7 @@ Vector<AST::Command> Shell::expand_aliases(Vector<AST::Command> initial_commands subcommand_nonnull, adopt_ref(*new AST::CommandLiteral(subcommand_nonnull->position(), command)))); auto res = substitute->run(*this); - for (auto& subst_command : res->resolve_as_commands(*this)) { + for (auto& subst_command : res->resolve_as_commands(*this).release_value_but_fixme_should_propagate_errors()) { if (!subst_command.argv.is_empty() && subst_command.argv.first() == argv0) // Disallow an alias resolving to itself. commands.append(subst_command); else @@ -364,7 +364,7 @@ RefPtr<AST::Value const> Shell::lookup_local_variable(StringView name) const RefPtr<AST::Value const> Shell::get_argument(size_t index) const { if (index == 0) - return adopt_ref(*new AST::StringValue(current_script)); + return adopt_ref(*new AST::StringValue(String::from_deprecated_string(current_script).release_value_but_fixme_should_propagate_errors())); --index; if (auto argv = lookup_local_variable("ARGV"sv)) { @@ -390,7 +390,7 @@ DeprecatedString Shell::local_variable_or(StringView name, DeprecatedString cons auto value = lookup_local_variable(name); if (value) { StringBuilder builder; - builder.join(' ', const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this))); + builder.join(' ', const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this)).release_value_but_fixme_should_propagate_errors()); return builder.to_deprecated_string(); } return replacement; @@ -594,7 +594,7 @@ int Shell::run_command(StringView cmd, Optional<SourcePosition> source_position_ if (command->is_syntax_error()) { auto& error_node = command->syntax_error_node(); auto& position = error_node.position(); - raise_error(ShellError::EvaluatedSyntaxError, error_node.error_text(), position); + raise_error(ShellError::EvaluatedSyntaxError, error_node.error_text().bytes_as_string_view(), position); } if (!has_error(ShellError::None)) { @@ -673,7 +673,7 @@ ErrorOr<RefPtr<Job>> Shell::run_command(const AST::Command& command) auto apply_rewirings = [&]() -> ErrorOr<void> { for (auto& rewiring : rewirings) { - dbgln_if(SH_DEBUG, "in {}<{}>, dup2({}, {})", command.argv.is_empty() ? "(<Empty>)" : command.argv[0].characters(), getpid(), rewiring.old_fd, rewiring.new_fd); + dbgln_if(SH_DEBUG, "in {}<{}>, dup2({}, {})", command.argv.is_empty() ? "(<Empty>)"sv : command.argv[0], getpid(), rewiring.old_fd, rewiring.new_fd); int rc = dup2(rewiring.old_fd, rewiring.new_fd); if (rc < 0) return Error::from_syscall("dup2"sv, rc); @@ -734,11 +734,13 @@ ErrorOr<RefPtr<Job>> Shell::run_command(const AST::Command& command) } Vector<char const*> argv; - Vector<DeprecatedString> copy_argv = command.argv; + Vector<DeprecatedString> copy_argv; argv.ensure_capacity(command.argv.size() + 1); - for (auto& arg : copy_argv) - argv.append(arg.characters()); + for (auto& arg : command.argv) { + copy_argv.append(arg.to_deprecated_string()); + argv.append(copy_argv.last().characters()); + } argv.append(nullptr); @@ -1068,7 +1070,7 @@ bool Shell::is_allowed_to_modify_termios(const AST::Command& command) const if (!value) return false; - return const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this)).contains_slow(command.argv[0]); + return const_cast<AST::Value&>(*value).resolve_as_list(const_cast<Shell&>(*this)).release_value_but_fixme_should_propagate_errors().contains_slow(command.argv[0]); } void Shell::restore_ios() @@ -1665,29 +1667,27 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s if (command_node->would_execute()) return Error::from_string_literal("Refusing to complete nodes that would execute"); - DeprecatedString program_name_storage; + String program_name_storage; if (known_program_name.is_null()) { auto node = command_node->leftmost_trivial_literal(); if (!node) return Error::from_string_literal("Cannot complete"); - program_name_storage = const_cast<AST::Node&>(*node).run(*this)->resolve_as_string(*this); + program_name_storage = const_cast<AST::Node&>(*node).run(*this)->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); known_program_name = program_name_storage; } - auto program_name = known_program_name; - AST::Command completion_command; - completion_command.argv.append(program_name); + completion_command.argv.append(program_name_storage); completion_command = expand_aliases({ completion_command }).last(); - auto completion_utility_name = DeprecatedString::formatted("_complete_{}", completion_command.argv[0]); + auto completion_utility_name = String::formatted("_complete_{}", completion_command.argv[0]).release_value_but_fixme_should_propagate_errors(); if (binary_search(cached_path.span(), completion_utility_name, nullptr, RunnablePathComparator {}) != nullptr) completion_command.argv[0] = completion_utility_name; else if (!options.invoke_program_for_autocomplete) return Error::from_string_literal("Refusing to use the program itself as completion source"); - completion_command.argv.extend({ "--complete", "--" }); + completion_command.argv.extend({ String::from_utf8("--complete"sv).release_value_but_fixme_should_propagate_errors(), String::from_utf8_short_string("--"sv) }); struct Visitor : public AST::NodeVisitor { Visitor(Shell& shell, AST::Position position) @@ -1699,12 +1699,12 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s Shell& shell; AST::Position completion_position; - Vector<Vector<DeprecatedString>> lists; + Vector<Vector<String>> lists; bool fail { false }; void push_list() { lists.empend(); } - Vector<DeprecatedString> pop_list() { return lists.take_last(); } - Vector<DeprecatedString>& list() { return lists.last(); } + Vector<String> pop_list() { return lists.take_last(); } + Vector<String>& list() { return lists.last(); } bool should_include(AST::Node const* node) const { return node->position().end_offset <= completion_position.end_offset; } @@ -1717,7 +1717,7 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s virtual void visit(AST::BraceExpansion const* node) override { if (should_include(node)) - list().extend(static_cast<AST::Node*>(const_cast<AST::BraceExpansion*>(node))->run(shell)->resolve_as_list(shell)); + list().extend(static_cast<AST::Node*>(const_cast<AST::BraceExpansion*>(node))->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()); } virtual void visit(AST::CommandLiteral const* node) override @@ -1742,7 +1742,7 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s auto list = pop_list(); StringBuilder builder; builder.join(""sv, list); - this->list().append(builder.to_deprecated_string()); + this->list().append(builder.to_string().release_value_but_fixme_should_propagate_errors()); } virtual void visit(AST::Glob const* node) override @@ -1761,7 +1761,7 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s auto list = pop_list(); StringBuilder builder; builder.join(""sv, list); - this->list().append(builder.to_deprecated_string()); + this->list().append(builder.to_string().release_value_but_fixme_should_propagate_errors()); } virtual void visit(AST::ImmediateExpression const* node) override @@ -1783,13 +1783,13 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s virtual void visit(AST::SimpleVariable const* node) override { if (should_include(node)) - list().extend(static_cast<AST::Node*>(const_cast<AST::SimpleVariable*>(node))->run(shell)->resolve_as_list(shell)); + list().extend(static_cast<AST::Node*>(const_cast<AST::SimpleVariable*>(node))->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()); } virtual void visit(AST::SpecialVariable const* node) override { if (should_include(node)) - list().extend(static_cast<AST::Node*>(const_cast<AST::SpecialVariable*>(node))->run(shell)->resolve_as_list(shell)); + list().extend(static_cast<AST::Node*>(const_cast<AST::SpecialVariable*>(node))->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()); } virtual void visit(AST::Juxtaposition const* node) override @@ -1810,7 +1810,7 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s for (auto& right_entry : right) { builder.append(left_entry); builder.append(right_entry); - list().append(builder.to_deprecated_string()); + list().append(builder.to_string().release_value_but_fixme_should_propagate_errors()); builder.clear(); } } @@ -1825,7 +1825,7 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s virtual void visit(AST::Tilde const* node) override { if (should_include(node)) - list().extend(static_cast<AST::Node*>(const_cast<AST::Tilde*>(node))->run(shell)->resolve_as_list(shell)); + list().extend(static_cast<AST::Node*>(const_cast<AST::Tilde*>(node))->run(shell)->resolve_as_list(shell).release_value_but_fixme_should_propagate_errors()); } virtual void visit(AST::PathRedirectionNode const*) override { } @@ -1844,9 +1844,10 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s completion_command.argv.extend(visitor.list()); + auto devnull = String::from_utf8("/dev/null"sv).release_value_but_fixme_should_propagate_errors(); completion_command.should_wait = true; - completion_command.redirections.append(AST::PathRedirection::create("/dev/null", STDERR_FILENO, AST::PathRedirection::Write)); - completion_command.redirections.append(AST::PathRedirection::create("/dev/null", STDIN_FILENO, AST::PathRedirection::Read)); + completion_command.redirections.append(AST::PathRedirection::create(devnull, STDERR_FILENO, AST::PathRedirection::Write)); + completion_command.redirections.append(AST::PathRedirection::create(devnull, STDIN_FILENO, AST::PathRedirection::Read)); auto execute_node = make_ref_counted<AST::Execute>( AST::Position {}, @@ -1869,7 +1870,7 @@ ErrorOr<Vector<Line::CompletionSuggestion>> Shell::complete_via_program_itself(s { TemporaryChange change(m_is_interactive, false); execute_node->for_each_entry(*this, [&](NonnullRefPtr<AST::Value> entry) -> IterationDecision { - auto result = entry->resolve_as_string(*this); + auto result = entry->resolve_as_string(*this).release_value_but_fixme_should_propagate_errors(); JsonParser parser(result); auto parsed_result = parser.parse(); if (parsed_result.is_error()) diff --git a/Userland/Shell/main.cpp b/Userland/Shell/main.cpp index 043e43c0e9..1ed6c8803e 100644 --- a/Userland/Shell/main.cpp +++ b/Userland/Shell/main.cpp @@ -165,7 +165,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) StringView command_to_run = {}; StringView file_to_read_from = {}; - Vector<DeprecatedString> script_args; + Vector<StringView> script_args; bool skip_rc_files = false; char const* format = nullptr; bool should_format_live = false; @@ -236,7 +236,12 @@ ErrorOr<int> serenity_main(Main::Arguments arguments) shell->cache_path(); } - shell->set_local_variable("ARGV", adopt_ref(*new Shell::AST::ListValue(move(script_args)))); + Vector<String> args_to_pass; + TRY(args_to_pass.try_ensure_capacity(script_args.size())); + for (auto& arg : script_args) + TRY(args_to_pass.try_append(TRY(String::from_utf8(arg)))); + + shell->set_local_variable("ARGV", adopt_ref(*new Shell::AST::ListValue(move(args_to_pass)))); if (!command_to_run.is_empty()) { auto result = shell->run_command(command_to_run); |