Skip to main content

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}