cmakefmt/parser/ast.rs
1// SPDX-FileCopyrightText: Copyright 2026 Puneet Matharu
2//
3// SPDX-License-Identifier: MIT OR Apache-2.0
4
5/// A parsed CMake source file.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct File {
8 /// Top-level statements in source order.
9 pub statements: Vec<Statement>,
10}
11
12/// A top-level statement in a CMake file.
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub enum Statement {
15 /// A command invocation, e.g. `target_link_libraries(foo PUBLIC bar)`.
16 Command(CommandInvocation),
17 /// A top-level configure-file placeholder line such as `@PACKAGE_INIT@`.
18 ///
19 /// These occur in `.cmake.in` templates and must be preserved verbatim.
20 TemplatePlaceholder(String),
21 /// A standalone comment (on its own line).
22 Comment(Comment),
23 /// One or more consecutive blank lines between statements.
24 /// The value is the number of blank lines (>= 1).
25 BlankLines(usize),
26}
27
28/// A CMake command invocation.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct CommandInvocation {
31 /// The command name, e.g. "target_link_libraries". Case as written in source.
32 pub name: String,
33 /// The argument list, in source order.
34 pub arguments: Vec<Argument>,
35 /// A comment that appears after the closing paren on the same line.
36 pub trailing_comment: Option<Comment>,
37 /// Byte span (start, end) in the original source.
38 pub span: (usize, usize),
39}
40
41/// A single argument (or inline comment) in an argument list.
42#[derive(Debug, Clone, PartialEq, Eq)]
43pub enum Argument {
44 /// `[[...]]`, `[=[...]=]`, etc. Content is verbatim.
45 Bracket(BracketArgument),
46 /// `"..."` — includes the surrounding quotes verbatim.
47 Quoted(String),
48 /// Any other token — unquoted argument, variable ref, generator expr.
49 Unquoted(String),
50 /// A comment that appears inline between arguments.
51 InlineComment(Comment),
52}
53
54impl Argument {
55 /// The source text of this argument.
56 pub fn as_str(&self) -> &str {
57 match self {
58 Argument::Bracket(b) => &b.raw,
59 Argument::Quoted(s) | Argument::Unquoted(s) => s,
60 Argument::InlineComment(c) => c.as_str(),
61 }
62 }
63
64 /// Returns `true` when the argument is an inline comment placeholder rather
65 /// than a normal CMake argument token.
66 pub fn is_comment(&self) -> bool {
67 matches!(self, Argument::InlineComment(_))
68 }
69}
70
71/// A bracket argument with its "=" nesting level.
72#[derive(Debug, Clone, PartialEq, Eq)]
73pub struct BracketArgument {
74 /// Number of `=` characters between the outer brackets. 0 = `[[...]]`.
75 pub level: usize,
76 /// The raw source text, e.g. `[==[content]==]`.
77 pub raw: String,
78}
79
80/// A CMake comment.
81#[derive(Debug, Clone, PartialEq, Eq)]
82pub enum Comment {
83 /// `# text to end of line` (stored with the leading `#`).
84 Line(String),
85 /// `#[[...]]` or `#[=[...]=]` (stored as the full raw text including `#`).
86 Bracket(String),
87}
88
89impl Comment {
90 /// Return the raw source text of the comment, including the leading `#`.
91 pub fn as_str(&self) -> &str {
92 match self {
93 Comment::Line(s) | Comment::Bracket(s) => s,
94 }
95 }
96}