Coverage Report

Created: 2025-11-16 07:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibShell/AST.h
Line
Count
Source
1
/*
2
 * Copyright (c) 2020, the SerenityOS developers.
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#pragma once
8
9
#include "Forward.h"
10
#include "Job.h"
11
#include "NodeVisitor.h"
12
#include <AK/Format.h>
13
#include <AK/NonnullRefPtr.h>
14
#include <AK/RefCounted.h>
15
#include <AK/RefPtr.h>
16
#include <AK/String.h>
17
#include <AK/Types.h>
18
#include <AK/Vector.h>
19
#include <LibLine/Editor.h>
20
#include <LibRegex/Regex.h>
21
22
namespace Shell::AST {
23
24
using AK::make_ref_counted;
25
26
template<typename T>
27
static inline NonnullRefPtr<T> make_ref_counted(std::initializer_list<NonnullRefPtr<Value>> arg)
28
0
{
29
0
    return adopt_ref(*new T(arg));
30
0
}
31
32
struct HighlightMetadata {
33
    bool is_first_in_list { true };
34
};
35
36
struct Position {
37
    size_t start_offset { 0 };
38
    size_t end_offset { 0 };
39
    struct Line {
40
        size_t line_number { 0 };
41
        size_t line_column { 0 };
42
43
        bool operator==(Line const& other) const
44
54.2M
        {
45
54.2M
            return line_number == other.line_number && line_column == other.line_column;
46
54.2M
        }
47
    } start_line, end_line;
48
49
0
    bool contains(size_t offset) const { return start_offset <= offset && offset <= end_offset; }
50
51
    Position with_end(Position const& end) const
52
6.76M
    {
53
6.76M
        return {
54
6.76M
            .start_offset = start_offset,
55
6.76M
            .end_offset = end.end_offset,
56
6.76M
            .start_line = start_line,
57
6.76M
            .end_line = end.end_line,
58
6.76M
        };
59
6.76M
    }
60
};
61
62
struct NameWithPosition {
63
    String name;
64
    Position position;
65
};
66
67
struct FdRedirection;
68
struct Rewiring : public RefCounted<Rewiring> {
69
    int old_fd { -1 };
70
    int new_fd { -1 };
71
    FdRedirection* other_pipe_end { nullptr };
72
    enum class Close {
73
        None,
74
        Old,
75
        New,
76
        RefreshNew,
77
        RefreshOld,
78
        ImmediatelyCloseNew,
79
    } fd_action { Close::None };
80
81
    Rewiring(int source, int dest, Close close = Close::None)
82
0
        : old_fd(source)
83
0
        , new_fd(dest)
84
0
        , fd_action(close)
85
0
    {
86
0
    }
87
88
    Rewiring(int source, int dest, FdRedirection* other_end, Close close)
89
0
        : old_fd(source)
90
0
        , new_fd(dest)
91
0
        , other_pipe_end(other_end)
92
0
        , fd_action(close)
93
0
    {
94
0
    }
95
};
96
97
struct Redirection : public RefCounted<Redirection> {
98
    virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const = 0;
99
    virtual ~Redirection();
100
0
    virtual bool is_path_redirection() const { return false; }
101
0
    virtual bool is_fd_redirection() const { return false; }
102
0
    virtual bool is_close_redirection() const { return false; }
103
};
104
105
struct CloseRedirection : public Redirection {
106
    int fd { -1 };
107
108
    virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const override;
109
    virtual ~CloseRedirection();
110
    CloseRedirection(int fd)
111
0
        : fd(fd)
112
0
    {
113
0
    }
114
115
private:
116
0
    virtual bool is_close_redirection() const override { return true; }
117
};
118
119
struct PathRedirection : public Redirection {
120
    String path;
121
    int fd { -1 };
122
    enum {
123
        Read,
124
        Write,
125
        WriteAppend,
126
        ReadWrite,
127
    } direction { Read };
128
129
    static NonnullRefPtr<PathRedirection> create(String path, int fd, decltype(direction) direction)
130
0
    {
131
0
        return adopt_ref(*new PathRedirection(move(path), fd, direction));
132
0
    }
133
134
    virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const override;
135
    virtual ~PathRedirection();
136
137
private:
138
    PathRedirection(String path, int fd, decltype(direction) direction)
139
0
        : path(move(path))
140
0
        , fd(fd)
141
0
        , direction(direction)
142
0
    {
143
0
    }
144
145
0
    virtual bool is_path_redirection() const override { return true; }
146
};
147
148
struct FdRedirection : public Redirection {
149
public:
150
    static NonnullRefPtr<FdRedirection> create(int old_fd, int new_fd, Rewiring::Close close)
151
0
    {
152
0
        return adopt_ref(*new FdRedirection(old_fd, new_fd, close));
153
0
    }
154
155
    static NonnullRefPtr<FdRedirection> create(int old_fd, int new_fd, FdRedirection* pipe_end, Rewiring::Close close)
156
0
    {
157
0
        return adopt_ref(*new FdRedirection(old_fd, new_fd, pipe_end, close));
158
0
    }
159
160
    virtual ~FdRedirection();
161
162
    virtual ErrorOr<NonnullRefPtr<Rewiring>> apply() const override
163
0
    {
164
0
        return adopt_ref(*new Rewiring(old_fd, new_fd, other_pipe_end, action));
165
0
    }
166
167
    int old_fd { -1 };
168
    int new_fd { -1 };
169
    FdRedirection* other_pipe_end { nullptr };
170
    Rewiring::Close action { Rewiring::Close::None };
171
172
private:
173
    FdRedirection(int source, int dest, Rewiring::Close close)
174
0
        : FdRedirection(source, dest, nullptr, close)
175
0
    {
176
0
    }
177
178
    FdRedirection(int old_fd, int new_fd, FdRedirection* pipe_end, Rewiring::Close close)
179
0
        : old_fd(old_fd)
180
0
        , new_fd(new_fd)
181
0
        , other_pipe_end(pipe_end)
182
0
        , action(close)
183
0
    {
184
0
    }
185
186
0
    virtual bool is_fd_redirection() const override { return true; }
187
};
188
189
class Pipeline : public RefCounted<Pipeline> {
190
public:
191
    pid_t pgid { -1 };
192
};
193
194
struct NodeWithAction {
195
    mutable NonnullRefPtr<Node> node;
196
    enum Action {
197
        And,
198
        Or,
199
        Sequence,
200
    } action;
201
202
    NodeWithAction(Node& node, Action action)
203
0
        : node(node)
204
0
        , action(action)
205
0
    {
206
0
    }
207
};
208
209
struct Command {
210
    Vector<String> argv;
211
    Vector<NonnullRefPtr<Redirection>> redirections;
212
    bool should_wait { true };
213
    bool is_pipe_source { false };
214
    bool should_notify_if_in_background { true };
215
    bool should_immediately_execute_next { false };
216
217
    mutable RefPtr<Pipeline> pipeline;
218
    Vector<NodeWithAction> next_chain;
219
    Optional<Position> position;
220
};
221
222
struct HitTestResult {
223
    RefPtr<Node const> matching_node;
224
    RefPtr<Node const> closest_node_with_semantic_meaning; // This is used if matching_node is a bareword
225
    RefPtr<Node const> closest_command_node;               // This is used if matching_node is a bareword, and it is not the first in a list
226
};
227
228
class Value : public RefCounted<Value> {
229
public:
230
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) = 0;
231
    virtual ErrorOr<String> resolve_as_string(RefPtr<Shell> shell);
232
    virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>);
233
0
    virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) { return *this; }
234
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const = 0;
235
    virtual ErrorOr<NonnullRefPtr<Value>> with_slices(NonnullRefPtr<Slice> slice) const&;
236
    virtual ErrorOr<NonnullRefPtr<Value>> with_slices(Vector<NonnullRefPtr<Slice>> slices) const&;
237
    virtual ~Value();
238
0
    virtual bool is_command() const { return false; }
239
0
    virtual bool is_glob() const { return false; }
240
0
    virtual bool is_job() const { return false; }
241
0
    virtual bool is_list() const { return false; }
242
0
    virtual bool is_string() const { return false; }
243
0
    virtual bool is_list_without_resolution() const { return false; }
244
245
protected:
246
    Value& set_slices(Vector<NonnullRefPtr<Slice>> slices)
247
0
    {
248
0
        m_slices = move(slices);
249
0
        return *this;
250
0
    }
251
    Vector<NonnullRefPtr<Slice>> m_slices;
252
};
253
254
class CommandValue final : public Value {
255
public:
256
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
257
    virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override;
258
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<CommandValue>(m_command))->set_slices(m_slices); }
259
    virtual ~CommandValue();
260
0
    virtual bool is_command() const override { return true; }
261
    CommandValue(Command command)
262
0
        : m_command(move(command))
263
0
    {
264
0
    }
265
266
    CommandValue(Vector<String> argv, Position position)
267
0
        : m_command({ move(argv), {}, true, false, true, false, nullptr, {}, move(position) })
268
0
    {
269
0
    }
270
271
private:
272
    Command m_command;
273
};
274
275
class CommandSequenceValue final : public Value {
276
public:
277
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
278
    virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override;
279
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<CommandSequenceValue>(m_contained_values))->set_slices(m_slices); }
280
    virtual ~CommandSequenceValue();
281
0
    virtual bool is_command() const override { return true; }
282
    CommandSequenceValue(Vector<Command> commands)
283
0
        : m_contained_values(move(commands))
284
0
    {
285
0
    }
286
287
private:
288
    Vector<Command> m_contained_values;
289
};
290
291
class JobValue final : public Value {
292
public:
293
0
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); }
294
0
    virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override { return String::formatted("%{}", m_job->job_id()); }
295
0
    virtual ErrorOr<Vector<Command>> resolve_as_commands(RefPtr<Shell>) override { VERIFY_NOT_REACHED(); }
296
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<JobValue>(m_job))->set_slices(m_slices); }
297
    virtual ~JobValue();
298
0
    virtual bool is_job() const override { return true; }
299
    JobValue(RefPtr<Job> job)
300
0
        : m_job(move(job))
301
0
    {
302
0
    }
303
304
0
    RefPtr<Job> const job() const { return m_job; }
305
306
private:
307
    RefPtr<Job> m_job;
308
};
309
310
class ListValue final : public Value {
311
public:
312
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
313
    virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
314
    virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
315
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<ListValue>(m_contained_values))->set_slices(m_slices); }
316
    virtual ~ListValue();
317
0
    virtual bool is_list() const override { return true; }
318
0
    virtual bool is_list_without_resolution() const override { return true; }
319
    ListValue(Vector<String> values);
320
    ListValue(Vector<NonnullRefPtr<Value>> values)
321
0
        : m_contained_values(move(values))
322
0
    {
323
0
    }
324
325
0
    Vector<NonnullRefPtr<Value>> const& values() const { return m_contained_values; }
326
0
    Vector<NonnullRefPtr<Value>>& values() { return m_contained_values; }
327
328
private:
329
    Vector<NonnullRefPtr<Value>> m_contained_values;
330
};
331
332
class StringValue final : public Value {
333
public:
334
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
335
    virtual ErrorOr<String> resolve_as_string(RefPtr<Shell> shell) override;
336
0
    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); }
337
    virtual ~StringValue();
338
0
    virtual bool is_string() const override { return m_split.is_empty(); }
339
0
    virtual bool is_list() const override { return !m_split.is_empty(); }
340
    ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
341
    StringValue(String string, String split_by = {}, bool keep_empty = false)
342
0
        : m_string(move(string))
343
0
        , m_split(move(split_by))
344
0
        , m_keep_empty(keep_empty)
345
0
    {
346
0
    }
347
348
private:
349
    String m_string;
350
    String m_split;
351
    bool m_keep_empty { false };
352
};
353
354
class GlobValue final : public Value {
355
public:
356
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
357
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<GlobValue>(m_glob, m_generation_position))->set_slices(m_slices); }
358
    virtual ~GlobValue();
359
0
    virtual bool is_glob() const override { return true; }
360
    GlobValue(String glob, Position position)
361
0
        : m_glob(move(glob))
362
0
        , m_generation_position(move(position))
363
0
    {
364
0
    }
365
366
private:
367
    String m_glob;
368
    Position m_generation_position;
369
};
370
371
class SimpleVariableValue final : public Value {
372
public:
373
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
374
    virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
375
    virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
376
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<SimpleVariableValue>(m_name))->set_slices(m_slices); }
377
    virtual ~SimpleVariableValue();
378
    SimpleVariableValue(String name)
379
0
        : m_name(move(name))
380
0
    {
381
0
    }
382
383
private:
384
    String m_name;
385
};
386
387
class SpecialVariableValue final : public Value {
388
public:
389
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
390
    virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
391
    virtual ErrorOr<NonnullRefPtr<Value>> resolve_without_cast(RefPtr<Shell>) override;
392
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<SpecialVariableValue>(m_name))->set_slices(m_slices); }
393
    virtual ~SpecialVariableValue();
394
    SpecialVariableValue(char name)
395
0
        : m_name(name)
396
0
    {
397
0
    }
398
399
private:
400
    char m_name { 0 };
401
};
402
403
class TildeValue final : public Value {
404
public:
405
    virtual ErrorOr<Vector<String>> resolve_as_list(RefPtr<Shell>) override;
406
    virtual ErrorOr<String> resolve_as_string(RefPtr<Shell>) override;
407
0
    virtual ErrorOr<NonnullRefPtr<Value>> clone() const override { return TRY(try_make_ref_counted<TildeValue>(m_username))->set_slices(m_slices); }
408
    virtual ~TildeValue();
409
0
    virtual bool is_string() const override { return true; }
410
    TildeValue(String name)
411
0
        : m_username(move(name))
412
0
    {
413
0
    }
414
415
private:
416
    String m_username;
417
};
418
419
class Node : public RefCounted<Node> {
420
    AK_MAKE_NONCOPYABLE(Node);
421
    AK_MAKE_NONMOVABLE(Node);
422
423
public:
424
    virtual ErrorOr<void> dump(int level) const = 0;
425
    virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback);
426
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) = 0;
427
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) = 0;
428
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const;
429
    ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell& shell, size_t offset);
430
    virtual HitTestResult hit_test_position(size_t offset) const
431
0
    {
432
0
        if (m_position.contains(offset))
433
0
            return { this, nullptr, nullptr };
434
0
        return { nullptr, nullptr, nullptr };
435
0
    }
436
0
    virtual StringView class_name() const { return "Node"sv; }
437
    Node(Position);
438
27.7M
    virtual ~Node() = default;
439
440
11.8k
    virtual bool is_bareword() const { return false; }
441
0
    virtual bool is_command() const { return false; }
442
40.4k
    virtual bool is_execute() const { return false; }
443
5.73k
    virtual bool is_glob() const { return false; }
444
3.07k
    virtual bool is_tilde() const { return false; }
445
0
    virtual bool is_variable_decls() const { return false; }
446
0
    virtual bool is_simple_variable() const { return false; }
447
    virtual bool is_syntax_error() const;
448
449
29.0k
    virtual bool is_list() const { return false; }
450
0
    virtual bool would_execute() const { return false; }
451
0
    virtual bool should_override_execution_in_current_process() const { return false; }
452
453
0
    Position const& position() const { return m_position; }
454
7.03M
    Position& position() { return m_position; }
455
    virtual void clear_syntax_error();
456
    virtual void set_is_syntax_error(SyntaxError& error_node);
457
    virtual SyntaxError& syntax_error_node()
458
2.51M
    {
459
2.51M
        VERIFY(is_syntax_error());
460
2.51M
        return *m_syntax_error_node;
461
2.51M
    }
462
463
0
    virtual RefPtr<Node const> leftmost_trivial_literal() const { return nullptr; }
464
465
    ErrorOr<Vector<Command>> to_lazy_evaluated_commands(RefPtr<Shell> shell);
466
467
0
    virtual void visit(NodeVisitor&) { VERIFY_NOT_REACHED(); }
468
0
    virtual void visit(NodeVisitor& visitor) const { const_cast<Node*>(this)->visit(visitor); }
469
470
    enum class Kind : u32 {
471
        And,
472
        Background,
473
        BarewordLiteral,
474
        BraceExpansion,
475
        CastToCommand,
476
        CastToList,
477
        CloseFdRedirection,
478
        CommandLiteral,
479
        Comment,
480
        ContinuationControl,
481
        DoubleQuotedString,
482
        DynamicEvaluate,
483
        Execute,
484
        Fd2FdRedirection,
485
        ForLoop,
486
        FunctionDeclaration,
487
        Glob,
488
        Heredoc,
489
        HistoryEvent,
490
        IfCond,
491
        ImmediateExpression,
492
        Join,
493
        Juxtaposition,
494
        ListConcatenate,
495
        MatchExpr,
496
        Or,
497
        Pipe,
498
        Range,
499
        ReadRedirection,
500
        ReadWriteRedirection,
501
        Sequence,
502
        Slice,
503
        SimpleVariable,
504
        SpecialVariable,
505
        StringLiteral,
506
        StringPartCompose,
507
        Subshell,
508
        SyntaxError,
509
        SyntheticValue,
510
        Tilde,
511
        VariableDeclarations,
512
        WriteAppendRedirection,
513
        WriteRedirection,
514
        __Count,
515
    };
516
517
    virtual Kind kind() const = 0;
518
519
protected:
520
    Position m_position;
521
    RefPtr<SyntaxError> m_syntax_error_node;
522
};
523
524
#define NODE(name)                                 \
525
    virtual StringView class_name() const override \
526
11.8k
    {                                              \
527
11.8k
        return #name##sv;                          \
528
11.8k
    }                                              \
Unexecuted instantiation: Shell::AST::And::class_name() const
Unexecuted instantiation: Shell::AST::ListConcatenate::class_name() const
Unexecuted instantiation: Shell::AST::Background::class_name() const
Unexecuted instantiation: Shell::AST::BarewordLiteral::class_name() const
Unexecuted instantiation: Shell::AST::BraceExpansion::class_name() const
Unexecuted instantiation: Shell::AST::CastToCommand::class_name() const
Unexecuted instantiation: Shell::AST::CastToList::class_name() const
Unexecuted instantiation: Shell::AST::CloseFdRedirection::class_name() const
Unexecuted instantiation: Shell::AST::CommandLiteral::class_name() const
Unexecuted instantiation: Shell::AST::Comment::class_name() const
Unexecuted instantiation: Shell::AST::ContinuationControl::class_name() const
Unexecuted instantiation: Shell::AST::DynamicEvaluate::class_name() const
Unexecuted instantiation: Shell::AST::DoubleQuotedString::class_name() const
Unexecuted instantiation: Shell::AST::Fd2FdRedirection::class_name() const
Unexecuted instantiation: Shell::AST::FunctionDeclaration::class_name() const
Unexecuted instantiation: Shell::AST::ForLoop::class_name() const
Unexecuted instantiation: Shell::AST::Glob::class_name() const
Unexecuted instantiation: Shell::AST::HistoryEvent::class_name() const
Unexecuted instantiation: Shell::AST::Execute::class_name() const
Unexecuted instantiation: Shell::AST::IfCond::class_name() const
Unexecuted instantiation: Shell::AST::ImmediateExpression::class_name() const
Unexecuted instantiation: Shell::AST::Join::class_name() const
Unexecuted instantiation: Shell::AST::MatchExpr::class_name() const
Unexecuted instantiation: Shell::AST::Or::class_name() const
Unexecuted instantiation: Shell::AST::Pipe::class_name() const
Unexecuted instantiation: Shell::AST::Range::class_name() const
Unexecuted instantiation: Shell::AST::ReadRedirection::class_name() const
Unexecuted instantiation: Shell::AST::ReadWriteRedirection::class_name() const
Unexecuted instantiation: Shell::AST::Sequence::class_name() const
Unexecuted instantiation: Shell::AST::Subshell::class_name() const
Unexecuted instantiation: Shell::AST::Slice::class_name() const
Unexecuted instantiation: Shell::AST::SimpleVariable::class_name() const
Unexecuted instantiation: Shell::AST::SpecialVariable::class_name() const
Shell::AST::Juxtaposition::class_name() const
Line
Count
Source
526
2
    {                                              \
527
2
        return #name##sv;                          \
528
2
    }                                              \
Unexecuted instantiation: Shell::AST::Heredoc::class_name() const
Unexecuted instantiation: Shell::AST::StringLiteral::class_name() const
Unexecuted instantiation: Shell::AST::StringPartCompose::class_name() const
Shell::AST::SyntaxError::class_name() const
Line
Count
Source
526
5.40k
    {                                              \
527
5.40k
        return #name##sv;                          \
528
5.40k
    }                                              \
Unexecuted instantiation: Shell::AST::SyntheticNode::class_name() const
Shell::AST::Tilde::class_name() const
Line
Count
Source
526
6.44k
    {                                              \
527
6.44k
        return #name##sv;                          \
528
6.44k
    }                                              \
Unexecuted instantiation: Shell::AST::VariableDeclarations::class_name() const
Unexecuted instantiation: Shell::AST::WriteAppendRedirection::class_name() const
Unexecuted instantiation: Shell::AST::WriteRedirection::class_name() const
529
    virtual Kind kind() const override             \
530
0
    {                                              \
531
0
        return Kind::name;                         \
532
0
    }
Unexecuted instantiation: Shell::AST::And::kind() const
Unexecuted instantiation: Shell::AST::ListConcatenate::kind() const
Unexecuted instantiation: Shell::AST::Background::kind() const
Unexecuted instantiation: Shell::AST::BarewordLiteral::kind() const
Unexecuted instantiation: Shell::AST::BraceExpansion::kind() const
Unexecuted instantiation: Shell::AST::CastToCommand::kind() const
Unexecuted instantiation: Shell::AST::CastToList::kind() const
Unexecuted instantiation: Shell::AST::CloseFdRedirection::kind() const
Unexecuted instantiation: Shell::AST::CommandLiteral::kind() const
Unexecuted instantiation: Shell::AST::Comment::kind() const
Unexecuted instantiation: Shell::AST::ContinuationControl::kind() const
Unexecuted instantiation: Shell::AST::DynamicEvaluate::kind() const
Unexecuted instantiation: Shell::AST::DoubleQuotedString::kind() const
Unexecuted instantiation: Shell::AST::Fd2FdRedirection::kind() const
Unexecuted instantiation: Shell::AST::FunctionDeclaration::kind() const
Unexecuted instantiation: Shell::AST::ForLoop::kind() const
Unexecuted instantiation: Shell::AST::Glob::kind() const
Unexecuted instantiation: Shell::AST::HistoryEvent::kind() const
Unexecuted instantiation: Shell::AST::Execute::kind() const
Unexecuted instantiation: Shell::AST::IfCond::kind() const
Unexecuted instantiation: Shell::AST::ImmediateExpression::kind() const
Unexecuted instantiation: Shell::AST::Join::kind() const
Unexecuted instantiation: Shell::AST::MatchExpr::kind() const
Unexecuted instantiation: Shell::AST::Or::kind() const
Unexecuted instantiation: Shell::AST::Pipe::kind() const
Unexecuted instantiation: Shell::AST::Range::kind() const
Unexecuted instantiation: Shell::AST::ReadRedirection::kind() const
Unexecuted instantiation: Shell::AST::ReadWriteRedirection::kind() const
Unexecuted instantiation: Shell::AST::Sequence::kind() const
Unexecuted instantiation: Shell::AST::Subshell::kind() const
Unexecuted instantiation: Shell::AST::Slice::kind() const
Unexecuted instantiation: Shell::AST::SimpleVariable::kind() const
Unexecuted instantiation: Shell::AST::SpecialVariable::kind() const
Unexecuted instantiation: Shell::AST::Juxtaposition::kind() const
Unexecuted instantiation: Shell::AST::Heredoc::kind() const
Unexecuted instantiation: Shell::AST::StringLiteral::kind() const
Unexecuted instantiation: Shell::AST::StringPartCompose::kind() const
Unexecuted instantiation: Shell::AST::SyntaxError::kind() const
Unexecuted instantiation: Shell::AST::SyntheticNode::kind() const
Unexecuted instantiation: Shell::AST::Tilde::kind() const
Unexecuted instantiation: Shell::AST::VariableDeclarations::kind() const
Unexecuted instantiation: Shell::AST::WriteAppendRedirection::kind() const
Unexecuted instantiation: Shell::AST::WriteRedirection::kind() const
533
534
class PathRedirectionNode : public Node {
535
public:
536
    PathRedirectionNode(Position, int, NonnullRefPtr<Node>);
537
    virtual ~PathRedirectionNode();
538
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
539
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
540
    virtual HitTestResult hit_test_position(size_t offset) const override;
541
0
    virtual bool is_command() const override { return true; }
542
0
    virtual bool is_list() const override { return true; }
543
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
544
545
0
    NonnullRefPtr<Node> const& path() const { return m_path; }
546
0
    int fd() const { return m_fd; }
547
548
protected:
549
    int m_fd { -1 };
550
    NonnullRefPtr<Node> m_path;
551
};
552
553
class And final : public Node {
554
public:
555
    And(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>, Position and_position);
556
25.8k
    virtual ~And() = default;
557
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
558
559
0
    NonnullRefPtr<Node> const& left() const { return m_left; }
560
0
    NonnullRefPtr<Node> const& right() const { return m_right; }
561
0
    Position const& and_position() const { return m_and_position; }
562
563
private:
564
    NODE(And);
565
    virtual ErrorOr<void> dump(int level) const override;
566
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
567
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
568
    virtual HitTestResult hit_test_position(size_t) const override;
569
570
    NonnullRefPtr<Node> m_left;
571
    NonnullRefPtr<Node> m_right;
572
    Position m_and_position;
573
};
574
575
class ListConcatenate final : public Node {
576
public:
577
    ListConcatenate(Position, Vector<NonnullRefPtr<Node>>);
578
3.37M
    virtual ~ListConcatenate() = default;
579
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
580
0
    Vector<NonnullRefPtr<Node>> const list() const { return m_list; }
581
582
private:
583
    NODE(ListConcatenate);
584
    virtual ErrorOr<void> dump(int level) const override;
585
    virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback) override;
586
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
587
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
588
    virtual HitTestResult hit_test_position(size_t) const override;
589
0
    virtual bool is_list() const override { return true; }
590
    virtual RefPtr<Node const> leftmost_trivial_literal() const override;
591
592
    Vector<NonnullRefPtr<Node>> m_list;
593
};
594
595
class Background final : public Node {
596
public:
597
    Background(Position, NonnullRefPtr<Node>);
598
190k
    virtual ~Background() = default;
599
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
600
601
0
    NonnullRefPtr<Node> const& command() const { return m_command; }
602
603
private:
604
    NODE(Background);
605
    virtual ErrorOr<void> dump(int level) const override;
606
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
607
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
608
    virtual HitTestResult hit_test_position(size_t) const override;
609
610
    NonnullRefPtr<Node> m_command;
611
};
612
613
class BarewordLiteral final : public Node {
614
public:
615
    BarewordLiteral(Position, String);
616
6.30M
    virtual ~BarewordLiteral() = default;
617
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
618
619
81.1k
    String const& text() const { return m_text; }
620
621
private:
622
    NODE(BarewordLiteral);
623
    virtual ErrorOr<void> dump(int level) const override;
624
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
625
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
626
81.1k
    virtual bool is_bareword() const override { return true; }
627
0
    virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }
628
629
    String m_text;
630
};
631
632
class BraceExpansion final : public Node {
633
public:
634
    BraceExpansion(Position, Vector<NonnullRefPtr<Node>>);
635
67.2k
    virtual ~BraceExpansion() = default;
636
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
637
638
0
    Vector<NonnullRefPtr<Node>> const& entries() const { return m_entries; }
639
640
private:
641
    NODE(BraceExpansion);
642
    virtual ErrorOr<void> dump(int level) const override;
643
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
644
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
645
    virtual HitTestResult hit_test_position(size_t) const override;
646
647
    Vector<NonnullRefPtr<Node>> m_entries;
648
};
649
650
class CastToCommand final : public Node {
651
public:
652
    CastToCommand(Position, NonnullRefPtr<Node>);
653
3.37M
    virtual ~CastToCommand() = default;
654
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
655
656
2
    NonnullRefPtr<Node> const& inner() const { return m_inner; }
657
658
private:
659
    NODE(CastToCommand);
660
    virtual ErrorOr<void> dump(int level) const override;
661
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
662
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
663
    virtual HitTestResult hit_test_position(size_t) const override;
664
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
665
0
    virtual bool is_command() const override { return true; }
666
0
    virtual bool is_list() const override { return true; }
667
    virtual RefPtr<Node const> leftmost_trivial_literal() const override;
668
669
    NonnullRefPtr<Node> m_inner;
670
};
671
672
class CastToList final : public Node {
673
public:
674
    CastToList(Position, RefPtr<Node>);
675
17.9k
    virtual ~CastToList() = default;
676
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
677
678
0
    RefPtr<Node> const& inner() const { return m_inner; }
679
680
private:
681
    NODE(CastToList);
682
    virtual ErrorOr<void> dump(int level) const override;
683
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
684
    virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback) override;
685
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
686
    virtual HitTestResult hit_test_position(size_t) const override;
687
0
    virtual bool is_list() const override { return true; }
688
    virtual RefPtr<Node const> leftmost_trivial_literal() const override;
689
690
    RefPtr<Node> m_inner;
691
};
692
693
class CloseFdRedirection final : public Node {
694
public:
695
    CloseFdRedirection(Position, int);
696
    virtual ~CloseFdRedirection();
697
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
698
699
0
    int fd() const { return m_fd; }
700
701
private:
702
    NODE(CloseFdRedirection);
703
    virtual ErrorOr<void> dump(int level) const override;
704
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
705
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
706
0
    virtual bool is_command() const override { return true; }
707
708
    int m_fd { -1 };
709
};
710
711
class CommandLiteral final : public Node {
712
public:
713
    CommandLiteral(Position, Command);
714
    virtual ~CommandLiteral();
715
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
716
717
0
    Command const& command() const { return m_command; }
718
719
private:
720
    NODE(CommandLiteral);
721
    virtual ErrorOr<void> dump(int level) const override;
722
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
723
0
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override { VERIFY_NOT_REACHED(); }
724
0
    virtual bool is_command() const override { return true; }
725
0
    virtual bool is_list() const override { return true; }
726
727
    Command m_command;
728
};
729
730
class Comment : public Node {
731
public:
732
    Comment(Position, String);
733
    virtual ~Comment();
734
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
735
736
0
    String const& text() const { return m_text; }
737
738
private:
739
    NODE(Comment);
740
    virtual ErrorOr<void> dump(int level) const override;
741
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
742
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
743
744
    String m_text;
745
};
746
747
class ContinuationControl final : public Node {
748
public:
749
    enum ContinuationKind {
750
        Break,
751
        Continue,
752
    };
753
    ContinuationControl(Position position, ContinuationKind kind)
754
1.99k
        : Node(move(position))
755
1.99k
        , m_kind(kind)
756
1.99k
    {
757
1.99k
    }
758
    virtual ~ContinuationControl() = default;
759
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
760
761
0
    ContinuationKind continuation_kind() const { return m_kind; }
762
763
private:
764
    NODE(ContinuationControl);
765
766
    virtual ErrorOr<void> dump(int level) const override;
767
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
768
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
769
770
    ContinuationKind m_kind { ContinuationKind::Break };
771
};
772
773
class DynamicEvaluate final : public Node {
774
public:
775
    DynamicEvaluate(Position, NonnullRefPtr<Node>);
776
    virtual ~DynamicEvaluate();
777
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
778
779
0
    NonnullRefPtr<Node> const& inner() const { return m_inner; }
780
781
private:
782
    NODE(DynamicEvaluate);
783
    virtual ErrorOr<void> dump(int level) const override;
784
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
785
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
786
    virtual HitTestResult hit_test_position(size_t) const override;
787
788
0
    virtual bool is_bareword() const override { return m_inner->is_bareword(); }
789
0
    virtual bool is_command() const override { return is_list(); }
790
0
    virtual bool is_execute() const override { return true; }
791
0
    virtual bool is_glob() const override { return m_inner->is_glob(); }
792
    virtual bool is_list() const override
793
0
    {
794
0
        return m_inner->is_list() || m_inner->is_command() || m_inner->is_glob(); // Anything that generates a list.
795
0
    }
796
797
    NonnullRefPtr<Node> m_inner;
798
};
799
800
class DoubleQuotedString final : public Node {
801
public:
802
    DoubleQuotedString(Position, RefPtr<Node>);
803
    virtual ~DoubleQuotedString();
804
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
805
806
0
    RefPtr<Node> const& inner() const { return m_inner; }
807
808
private:
809
    NODE(DoubleQuotedString);
810
    virtual ErrorOr<void> dump(int level) const override;
811
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
812
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
813
    virtual HitTestResult hit_test_position(size_t) const override;
814
815
    RefPtr<Node> m_inner;
816
};
817
818
class Fd2FdRedirection final : public Node {
819
public:
820
    Fd2FdRedirection(Position, int, int);
821
    virtual ~Fd2FdRedirection();
822
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
823
824
0
    int source_fd() const { return m_old_fd; }
825
0
    int dest_fd() const { return m_new_fd; }
826
827
private:
828
    NODE(Fd2FdRedirection);
829
    virtual ErrorOr<void> dump(int level) const override;
830
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
831
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
832
0
    virtual bool is_command() const override { return true; }
833
834
    int m_old_fd { -1 };
835
    int m_new_fd { -1 };
836
};
837
838
class FunctionDeclaration final : public Node {
839
public:
840
    FunctionDeclaration(Position, NameWithPosition name, Vector<NameWithPosition> argument_names, RefPtr<AST::Node> body);
841
    virtual ~FunctionDeclaration();
842
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
843
844
0
    NameWithPosition const& name() const { return m_name; }
845
0
    Vector<NameWithPosition> const arguments() const { return m_arguments; }
846
0
    RefPtr<Node> const& block() const { return m_block; }
847
848
private:
849
    NODE(FunctionDeclaration);
850
    virtual ErrorOr<void> dump(int level) const override;
851
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
852
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
853
    virtual HitTestResult hit_test_position(size_t) const override;
854
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
855
0
    virtual bool would_execute() const override { return true; }
856
0
    virtual bool should_override_execution_in_current_process() const override { return true; }
857
858
    NameWithPosition m_name;
859
    Vector<NameWithPosition> m_arguments;
860
    RefPtr<AST::Node> m_block;
861
};
862
863
class ForLoop final : public Node {
864
public:
865
    ForLoop(Position, Optional<NameWithPosition> variable, Optional<NameWithPosition> index_variable, RefPtr<AST::Node> iterated_expr, RefPtr<AST::Node> block, Optional<Position> in_kw_position = {}, Optional<Position> index_kw_position = {});
866
    virtual ~ForLoop();
867
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
868
869
0
    Optional<NameWithPosition> const& variable() const { return m_variable; }
870
0
    Optional<NameWithPosition> const& index_variable() const { return m_index_variable; }
871
0
    RefPtr<Node> const& iterated_expression() const { return m_iterated_expression; }
872
0
    RefPtr<Node> const& block() const { return m_block; }
873
0
    Optional<Position> const index_keyword_position() const { return m_index_kw_position; }
874
0
    Optional<Position> const in_keyword_position() const { return m_in_kw_position; }
875
876
private:
877
    NODE(ForLoop);
878
    virtual ErrorOr<void> dump(int level) const override;
879
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
880
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
881
    virtual HitTestResult hit_test_position(size_t) const override;
882
0
    virtual bool would_execute() const override { return true; }
883
0
    virtual bool should_override_execution_in_current_process() const override { return true; }
884
885
    Optional<NameWithPosition> m_variable;
886
    Optional<NameWithPosition> m_index_variable;
887
    RefPtr<AST::Node> m_iterated_expression;
888
    RefPtr<AST::Node> m_block;
889
    Optional<Position> m_in_kw_position;
890
    Optional<Position> m_index_kw_position;
891
};
892
893
class Glob final : public Node {
894
public:
895
    Glob(Position, String);
896
    virtual ~Glob();
897
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
898
899
569
    String const& text() const { return m_text; }
900
901
private:
902
    NODE(Glob);
903
    virtual ErrorOr<void> dump(int level) const override;
904
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
905
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
906
569
    virtual bool is_glob() const override { return true; }
907
0
    virtual bool is_list() const override { return true; }
908
909
    String m_text;
910
};
911
912
struct HistorySelector {
913
    enum EventKind {
914
        IndexFromStart,
915
        IndexFromEnd,
916
        StartingStringLookup,
917
        ContainingStringLookup,
918
    };
919
    enum WordSelectorKind {
920
        Index,
921
        Last,
922
    };
923
924
    struct {
925
        EventKind kind { IndexFromStart };
926
        size_t index { 0 };
927
        Position text_position;
928
        String text;
929
    } event;
930
931
    struct WordSelector {
932
        WordSelectorKind kind { Index };
933
        size_t selector { 0 };
934
        Position position;
935
        RefPtr<AST::SyntaxError> syntax_error_node;
936
937
        size_t resolve(size_t size) const
938
0
        {
939
0
            if (kind == Index)
940
0
                return selector;
941
0
            if (kind == Last)
942
0
                return size - selector - 1;
943
0
            VERIFY_NOT_REACHED();
944
0
        }
945
    };
946
    struct {
947
        WordSelector start;
948
        Optional<WordSelector> end;
949
    } word_selector_range;
950
};
951
952
class HistoryEvent final : public Node {
953
public:
954
    HistoryEvent(Position, HistorySelector);
955
    virtual ~HistoryEvent();
956
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
957
958
0
    HistorySelector const& selector() const { return m_selector; }
959
960
private:
961
    NODE(HistoryEvent);
962
    virtual ErrorOr<void> dump(int level) const override;
963
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
964
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
965
966
    HistorySelector m_selector;
967
};
968
969
class Execute final : public Node {
970
public:
971
    Execute(Position, NonnullRefPtr<Node>, bool capture_stdout = false);
972
    virtual ~Execute();
973
52.7k
    void capture_stdout() { m_capture_stdout = true; }
974
928
    NonnullRefPtr<Node>& command() { return m_command; }
975
    virtual ErrorOr<void> for_each_entry(RefPtr<Shell> shell, Function<ErrorOr<IterationDecision>(NonnullRefPtr<Value>)> callback) override;
976
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
977
978
0
    NonnullRefPtr<Node> const& command() const { return m_command; }
979
0
    bool does_capture_stdout() const { return m_capture_stdout; }
980
981
private:
982
    NODE(Execute);
983
    virtual ErrorOr<void> dump(int level) const override;
984
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
985
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
986
    virtual HitTestResult hit_test_position(size_t) const override;
987
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
988
53.6k
    virtual bool is_execute() const override { return true; }
989
0
    virtual bool would_execute() const override { return true; }
990
991
    NonnullRefPtr<Node> m_command;
992
    bool m_capture_stdout { false };
993
};
994
995
class IfCond final : public Node {
996
public:
997
    IfCond(Position, Optional<Position> else_position, NonnullRefPtr<AST::Node> cond_expr, RefPtr<AST::Node> true_branch, RefPtr<AST::Node> false_branch);
998
    virtual ~IfCond();
999
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1000
1001
0
    NonnullRefPtr<Node> const& condition() const { return m_condition; }
1002
0
    RefPtr<Node> const& true_branch() const { return m_true_branch; }
1003
0
    RefPtr<Node> const& false_branch() const { return m_false_branch; }
1004
26.3k
    RefPtr<Node>& false_branch() { return m_false_branch; }
1005
0
    Optional<Position> const else_position() const { return m_else_position; }
1006
1007
private:
1008
    NODE(IfCond);
1009
    virtual ErrorOr<void> dump(int level) const override;
1010
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1011
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1012
    virtual HitTestResult hit_test_position(size_t) const override;
1013
0
    virtual bool should_override_execution_in_current_process() const override { return true; }
1014
1015
    NonnullRefPtr<AST::Node> m_condition;
1016
    RefPtr<AST::Node> m_true_branch;
1017
    RefPtr<AST::Node> m_false_branch;
1018
1019
    Optional<Position> m_else_position;
1020
};
1021
1022
class ImmediateExpression final : public Node {
1023
public:
1024
    ImmediateExpression(Position, NameWithPosition function, Vector<NonnullRefPtr<AST::Node>> arguments, Optional<Position> closing_brace_position);
1025
    virtual ~ImmediateExpression();
1026
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1027
1028
0
    Vector<NonnullRefPtr<Node>> const& arguments() const { return m_arguments; }
1029
0
    auto const& function() const { return m_function; }
1030
2.51k
    String const& function_name() const { return m_function.name; }
1031
0
    Position const& function_position() const { return m_function.position; }
1032
0
    bool has_closing_brace() const { return m_closing_brace_position.has_value(); }
1033
1034
private:
1035
    NODE(ImmediateExpression);
1036
    virtual ErrorOr<void> dump(int level) const override;
1037
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1038
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1039
    ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
1040
    virtual HitTestResult hit_test_position(size_t) const override;
1041
1042
    Vector<NonnullRefPtr<AST::Node>> m_arguments;
1043
    NameWithPosition m_function;
1044
    Optional<Position> m_closing_brace_position;
1045
};
1046
1047
class Join final : public Node {
1048
public:
1049
    Join(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
1050
    virtual ~Join();
1051
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1052
1053
0
    NonnullRefPtr<Node> const& left() const { return m_left; }
1054
0
    NonnullRefPtr<Node> const& right() const { return m_right; }
1055
1056
private:
1057
    NODE(Join);
1058
    virtual ErrorOr<void> dump(int level) const override;
1059
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1060
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1061
    virtual HitTestResult hit_test_position(size_t) const override;
1062
0
    virtual bool is_command() const override { return true; }
1063
0
    virtual bool is_list() const override { return true; }
1064
    virtual RefPtr<Node const> leftmost_trivial_literal() const override;
1065
1066
    NonnullRefPtr<Node> m_left;
1067
    NonnullRefPtr<Node> m_right;
1068
};
1069
1070
struct MatchEntry {
1071
    Variant<Vector<NonnullRefPtr<Node>>, Vector<Regex<ECMA262>>> options;
1072
    Optional<Vector<String>> match_names;
1073
    Optional<Position> match_as_position;
1074
    Vector<Position> pipe_positions;
1075
    RefPtr<Node> body;
1076
};
1077
1078
class MatchExpr final : public Node {
1079
public:
1080
    MatchExpr(Position, NonnullRefPtr<Node> expr, String name, Optional<Position> as_position, Vector<MatchEntry> entries);
1081
    virtual ~MatchExpr();
1082
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1083
1084
0
    NonnullRefPtr<Node> const& matched_expr() const { return m_matched_expr; }
1085
0
    String const& expr_name() const { return m_expr_name; }
1086
0
    Vector<MatchEntry> const& entries() const { return m_entries; }
1087
0
    Optional<Position> const& as_position() const { return m_as_position; }
1088
1089
private:
1090
    NODE(MatchExpr);
1091
    virtual ErrorOr<void> dump(int level) const override;
1092
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1093
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1094
    virtual HitTestResult hit_test_position(size_t) const override;
1095
0
    virtual bool would_execute() const override { return true; }
1096
0
    virtual bool should_override_execution_in_current_process() const override { return true; }
1097
1098
    NonnullRefPtr<Node> m_matched_expr;
1099
    String m_expr_name;
1100
    Optional<Position> m_as_position;
1101
    Vector<MatchEntry> m_entries;
1102
};
1103
1104
class Or final : public Node {
1105
public:
1106
    Or(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>, Position or_position);
1107
    virtual ~Or();
1108
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1109
1110
0
    NonnullRefPtr<Node> const& left() const { return m_left; }
1111
0
    NonnullRefPtr<Node> const& right() const { return m_right; }
1112
0
    Position const& or_position() const { return m_or_position; }
1113
1114
private:
1115
    NODE(Or);
1116
    virtual ErrorOr<void> dump(int level) const override;
1117
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1118
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1119
    virtual HitTestResult hit_test_position(size_t) const override;
1120
1121
    NonnullRefPtr<Node> m_left;
1122
    NonnullRefPtr<Node> m_right;
1123
    Position m_or_position;
1124
};
1125
1126
class Pipe final : public Node {
1127
public:
1128
    Pipe(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
1129
    virtual ~Pipe();
1130
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1131
1132
0
    NonnullRefPtr<Node> const& left() const { return m_left; }
1133
0
    NonnullRefPtr<Node> const& right() const { return m_right; }
1134
1135
private:
1136
    NODE(Pipe);
1137
    virtual ErrorOr<void> dump(int level) const override;
1138
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1139
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1140
    virtual HitTestResult hit_test_position(size_t) const override;
1141
0
    virtual bool is_command() const override { return true; }
1142
1143
    NonnullRefPtr<Node> m_left;
1144
    NonnullRefPtr<Node> m_right;
1145
};
1146
1147
class Range final : public Node {
1148
public:
1149
    Range(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
1150
    virtual ~Range();
1151
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1152
1153
0
    NonnullRefPtr<Node> const& start() const { return m_start; }
1154
0
    NonnullRefPtr<Node> const& end() const { return m_end; }
1155
1156
private:
1157
    NODE(Range);
1158
    virtual ErrorOr<void> dump(int level) const override;
1159
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1160
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1161
    virtual HitTestResult hit_test_position(size_t) const override;
1162
1163
    NonnullRefPtr<Node> m_start;
1164
    NonnullRefPtr<Node> m_end;
1165
};
1166
1167
class ReadRedirection final : public PathRedirectionNode {
1168
public:
1169
    ReadRedirection(Position, int, NonnullRefPtr<Node>);
1170
    virtual ~ReadRedirection();
1171
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1172
1173
private:
1174
    NODE(ReadRedirection);
1175
    virtual ErrorOr<void> dump(int level) const override;
1176
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1177
};
1178
1179
class ReadWriteRedirection final : public PathRedirectionNode {
1180
public:
1181
    ReadWriteRedirection(Position, int, NonnullRefPtr<Node>);
1182
    virtual ~ReadWriteRedirection();
1183
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1184
1185
private:
1186
    NODE(ReadWriteRedirection);
1187
    virtual ErrorOr<void> dump(int level) const override;
1188
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1189
};
1190
1191
class Sequence final : public Node {
1192
public:
1193
    Sequence(Position, Vector<NonnullRefPtr<Node>>, Vector<Position> separator_positions);
1194
    virtual ~Sequence();
1195
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1196
1197
0
    Vector<NonnullRefPtr<Node>> const& entries() const { return m_entries; }
1198
1199
0
    Vector<Position> const& separator_positions() const { return m_separator_positions; }
1200
1201
private:
1202
    NODE(Sequence);
1203
    virtual ErrorOr<void> dump(int level) const override;
1204
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1205
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1206
    virtual HitTestResult hit_test_position(size_t) const override;
1207
0
    virtual bool is_list() const override { return true; }
1208
0
    virtual bool should_override_execution_in_current_process() const override { return true; }
1209
    virtual RefPtr<Node const> leftmost_trivial_literal() const override;
1210
1211
    Vector<NonnullRefPtr<Node>> m_entries;
1212
    Vector<Position> m_separator_positions;
1213
};
1214
1215
class Subshell final : public Node {
1216
public:
1217
    Subshell(Position, RefPtr<Node> block);
1218
    virtual ~Subshell();
1219
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1220
1221
0
    RefPtr<Node> const& block() const { return m_block; }
1222
1223
private:
1224
    NODE(Subshell);
1225
    virtual ErrorOr<void> dump(int level) const override;
1226
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1227
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1228
    virtual HitTestResult hit_test_position(size_t) const override;
1229
0
    virtual bool would_execute() const override { return false; }
1230
0
    virtual bool should_override_execution_in_current_process() const override { return true; }
1231
1232
    RefPtr<AST::Node> m_block;
1233
};
1234
1235
class Slice final : public Node {
1236
public:
1237
    Slice(Position, NonnullRefPtr<AST::Node>);
1238
    virtual ~Slice() override;
1239
1240
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1241
1242
0
    NonnullRefPtr<AST::Node> selector() const { return m_selector; }
1243
1244
    virtual ErrorOr<void> dump(int level) const override;
1245
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1246
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1247
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
1248
    virtual HitTestResult hit_test_position(size_t) const override;
1249
1250
protected:
1251
    NODE(Slice);
1252
    NonnullRefPtr<AST::Node> m_selector;
1253
};
1254
1255
class VariableNode : public Node {
1256
public:
1257
    VariableNode(Position position)
1258
546k
        : Node(move(position))
1259
546k
    {
1260
546k
    }
1261
1262
    void set_slice(NonnullRefPtr<Slice>&& slice)
1263
34.1k
    {
1264
34.1k
        VERIFY(!m_slice);
1265
34.1k
        m_slice = move(slice);
1266
34.1k
        if (m_slice->is_syntax_error())
1267
34.1k
            set_is_syntax_error(m_slice->syntax_error_node());
1268
34.1k
    }
1269
1270
0
    Slice const* slice() const { return m_slice.ptr(); }
1271
1272
protected:
1273
    RefPtr<Slice> m_slice;
1274
};
1275
1276
class SimpleVariable final : public VariableNode {
1277
public:
1278
    SimpleVariable(Position, String);
1279
    virtual ~SimpleVariable();
1280
1281
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1282
0
    String const& name() const { return m_name; }
1283
1284
private:
1285
    NODE(SimpleVariable);
1286
    virtual ErrorOr<void> dump(int level) const override;
1287
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1288
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1289
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
1290
    virtual HitTestResult hit_test_position(size_t) const override;
1291
0
    virtual bool is_simple_variable() const override { return true; }
1292
1293
    String m_name;
1294
};
1295
1296
class SpecialVariable final : public VariableNode {
1297
public:
1298
    SpecialVariable(Position, char);
1299
    virtual ~SpecialVariable();
1300
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1301
1302
0
    char name() const { return m_name; }
1303
1304
private:
1305
    NODE(SpecialVariable);
1306
    virtual ErrorOr<void> dump(int level) const override;
1307
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1308
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1309
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
1310
    virtual HitTestResult hit_test_position(size_t) const override;
1311
1312
    char m_name { 0 };
1313
};
1314
1315
class Juxtaposition final : public Node {
1316
public:
1317
    enum class Mode {
1318
        ListExpand,
1319
        StringExpand,
1320
    };
1321
    Juxtaposition(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>, Mode = Mode::ListExpand);
1322
    virtual ~Juxtaposition();
1323
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1324
1325
0
    NonnullRefPtr<Node> const& left() const { return m_left; }
1326
0
    NonnullRefPtr<Node> const& right() const { return m_right; }
1327
1328
private:
1329
    NODE(Juxtaposition);
1330
    virtual ErrorOr<void> dump(int level) const override;
1331
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1332
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1333
    virtual HitTestResult hit_test_position(size_t) const override;
1334
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
1335
1336
    NonnullRefPtr<Node> m_left;
1337
    NonnullRefPtr<Node> m_right;
1338
    Mode m_mode { Mode::ListExpand };
1339
};
1340
1341
class Heredoc final : public Node {
1342
public:
1343
    Heredoc(Position, String end, bool allow_interpolation, bool deindent, Optional<int> target_fd = {});
1344
    virtual ~Heredoc();
1345
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1346
1347
2.03k
    String const& end() const { return m_end; }
1348
724
    bool allow_interpolation() const { return m_allows_interpolation; }
1349
0
    bool deindent() const { return m_deindent; }
1350
0
    Optional<int> target_fd() const { return m_target_fd; }
1351
0
    bool evaluates_to_string() const { return !m_target_fd.has_value(); }
1352
0
    RefPtr<AST::Node> const& contents() const { return m_contents; }
1353
    void set_contents(RefPtr<AST::Node> contents)
1354
2.42k
    {
1355
2.42k
        m_contents = move(contents);
1356
2.42k
        if (m_contents->is_syntax_error())
1357
1.55k
            set_is_syntax_error(m_contents->syntax_error_node());
1358
874
        else if (is_syntax_error())
1359
575
            clear_syntax_error();
1360
2.42k
    }
1361
1362
private:
1363
    NODE(Heredoc);
1364
    virtual ErrorOr<void> dump(int level) const override;
1365
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1366
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1367
    virtual HitTestResult hit_test_position(size_t) const override;
1368
0
    virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }
1369
1370
    String m_end;
1371
    bool m_allows_interpolation { false };
1372
    bool m_deindent { false };
1373
    Optional<int> m_target_fd;
1374
    RefPtr<AST::Node> m_contents;
1375
};
1376
1377
class StringLiteral final : public Node {
1378
public:
1379
    enum class EnclosureType {
1380
        None,
1381
        SingleQuotes,
1382
        DoubleQuotes,
1383
    };
1384
1385
    StringLiteral(Position, String, EnclosureType);
1386
    virtual ~StringLiteral();
1387
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1388
1389
0
    String const& text() const { return m_text; }
1390
0
    EnclosureType enclosure_type() const { return m_enclosure_type; }
1391
1392
private:
1393
    NODE(StringLiteral);
1394
    virtual ErrorOr<void> dump(int level) const override;
1395
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1396
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1397
0
    virtual RefPtr<Node const> leftmost_trivial_literal() const override { return this; }
1398
1399
    String m_text;
1400
    EnclosureType m_enclosure_type;
1401
};
1402
1403
class StringPartCompose final : public Node {
1404
public:
1405
    StringPartCompose(Position, NonnullRefPtr<Node>, NonnullRefPtr<Node>);
1406
    virtual ~StringPartCompose();
1407
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1408
1409
0
    NonnullRefPtr<Node> const& left() const { return m_left; }
1410
0
    NonnullRefPtr<Node> const& right() const { return m_right; }
1411
1412
private:
1413
    NODE(StringPartCompose);
1414
    virtual ErrorOr<void> dump(int level) const override;
1415
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1416
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1417
    virtual HitTestResult hit_test_position(size_t) const override;
1418
1419
    NonnullRefPtr<Node> m_left;
1420
    NonnullRefPtr<Node> m_right;
1421
};
1422
1423
class SyntaxError final : public Node {
1424
public:
1425
    SyntaxError(Position, String, bool is_continuable = false);
1426
    virtual ~SyntaxError();
1427
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1428
1429
141k
    String const& error_text() const { return m_syntax_error_text; }
1430
0
    bool is_continuable() const { return m_is_continuable; }
1431
1432
    virtual void clear_syntax_error() override
1433
575
    {
1434
575
        m_is_cleared = true;
1435
575
    }
1436
    virtual void set_is_syntax_error(SyntaxError& error) override
1437
141k
    {
1438
141k
        m_position = error.position();
1439
141k
        m_is_cleared = error.m_is_cleared;
1440
141k
        m_is_continuable = error.m_is_continuable;
1441
141k
        m_syntax_error_text = error.error_text();
1442
141k
    }
1443
1444
5.85M
    virtual bool is_syntax_error() const override { return !m_is_cleared; }
1445
1446
private:
1447
    NODE(SyntaxError);
1448
    virtual ErrorOr<void> dump(int level) const override;
1449
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1450
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1451
0
    virtual HitTestResult hit_test_position(size_t) const override { return { nullptr, nullptr, nullptr }; }
1452
    virtual SyntaxError& syntax_error_node() override;
1453
1454
    String m_syntax_error_text;
1455
    bool m_is_continuable { false };
1456
    bool m_is_cleared { false };
1457
};
1458
1459
class SyntheticNode final : public Node {
1460
public:
1461
    SyntheticNode(Position, NonnullRefPtr<Value>);
1462
0
    virtual ~SyntheticNode() = default;
1463
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1464
1465
0
    Value const& value() const { return m_value; }
1466
1467
private:
1468
    NODE(SyntheticValue);
1469
    virtual ErrorOr<void> dump(int level) const override;
1470
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1471
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1472
1473
    NonnullRefPtr<Value> m_value;
1474
};
1475
1476
class Tilde final : public Node {
1477
public:
1478
    Tilde(Position, String);
1479
    virtual ~Tilde();
1480
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1481
1482
    String text() const;
1483
1484
private:
1485
    NODE(Tilde);
1486
    virtual ErrorOr<void> dump(int level) const override;
1487
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1488
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1489
    virtual ErrorOr<Vector<Line::CompletionSuggestion>> complete_for_editor(Shell&, size_t, HitTestResult const&) const override;
1490
    virtual HitTestResult hit_test_position(size_t) const override;
1491
4
    virtual bool is_tilde() const override { return true; }
1492
1493
    String m_username;
1494
};
1495
1496
class VariableDeclarations final : public Node {
1497
public:
1498
    struct Variable {
1499
        NonnullRefPtr<Node> name;
1500
        NonnullRefPtr<Node> value;
1501
    };
1502
    VariableDeclarations(Position, Vector<Variable> variables);
1503
    virtual ~VariableDeclarations();
1504
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1505
1506
0
    Vector<Variable> const& variables() const { return m_variables; }
1507
1508
private:
1509
    NODE(VariableDeclarations);
1510
    virtual ErrorOr<void> dump(int level) const override;
1511
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1512
    virtual ErrorOr<void> highlight_in_editor(Line::Editor&, Shell&, HighlightMetadata = {}) override;
1513
    virtual HitTestResult hit_test_position(size_t) const override;
1514
0
    virtual bool is_variable_decls() const override { return true; }
1515
1516
    Vector<Variable> m_variables;
1517
};
1518
1519
class WriteAppendRedirection final : public PathRedirectionNode {
1520
public:
1521
    WriteAppendRedirection(Position, int, NonnullRefPtr<Node>);
1522
    virtual ~WriteAppendRedirection();
1523
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1524
1525
private:
1526
    NODE(WriteAppendRedirection);
1527
    virtual ErrorOr<void> dump(int level) const override;
1528
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1529
};
1530
1531
class WriteRedirection final : public PathRedirectionNode {
1532
public:
1533
    WriteRedirection(Position, int, NonnullRefPtr<Node>);
1534
    virtual ~WriteRedirection();
1535
0
    virtual void visit(NodeVisitor& visitor) override { visitor.visit(this); }
1536
1537
private:
1538
    NODE(WriteRedirection);
1539
    virtual ErrorOr<void> dump(int level) const override;
1540
    virtual ErrorOr<RefPtr<Value>> run(RefPtr<Shell>) override;
1541
};
1542
1543
}
1544
1545
namespace AK {
1546
1547
template<>
1548
struct Formatter<Shell::AST::Command> : StandardFormatter {
1549
0
    Formatter() = default;
1550
    explicit Formatter(StandardFormatter formatter)
1551
        : StandardFormatter(formatter)
1552
0
    {
1553
0
    }
1554
1555
    ErrorOr<void> format(FormatBuilder&, Shell::AST::Command const& value);
1556
};
1557
1558
}