Coverage Report

Created: 2022-05-20 06:15

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