Skip to main content

solidity_language_server/solc_ast/
contracts.rs

1//! Contract definition and related AST node types.
2
3use serde::{Deserialize, Serialize};
4
5use super::{
6    ContractKind, Documentation, ErrorDefinition, EventDefinition, Expression, FunctionDefinition,
7    IdentifierPath, ModifierDefinition, NodeID, TypeName, UsingForFunction, VariableDeclaration,
8};
9
10/// A node that can appear inside a contract definition's `nodes` array.
11///
12/// Discriminated by `nodeType` in the JSON.
13#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
14#[serde(tag = "nodeType")]
15pub enum ContractDefinitionNode {
16    UsingForDirective(UsingForDirective),
17    StructDefinition(StructDefinition),
18    EnumDefinition(EnumDefinition),
19    VariableDeclaration(VariableDeclaration),
20    EventDefinition(EventDefinition),
21    ErrorDefinition(ErrorDefinition),
22    FunctionDefinition(FunctionDefinition),
23    ModifierDefinition(ModifierDefinition),
24    UserDefinedValueTypeDefinition(UserDefinedValueTypeDefinition),
25}
26
27impl ContractDefinitionNode {
28    /// Extract the function/error/event selector from this contract child node.
29    ///
30    /// Returns the hex selector string (no `0x` prefix):
31    /// - 4-byte for functions, public variables, and errors
32    /// - 32-byte for events
33    /// - `None` for other node types
34    pub fn selector(&self) -> Option<&str> {
35        match self {
36            Self::FunctionDefinition(n) => n.function_selector.as_deref(),
37            Self::VariableDeclaration(n) => n.function_selector.as_deref(),
38            Self::EventDefinition(n) => n.event_selector.as_deref(),
39            Self::ErrorDefinition(n) => n.error_selector.as_deref(),
40            _ => None,
41        }
42    }
43
44    /// Extract the documentation text from this contract child node.
45    pub fn documentation_text(&self) -> Option<String> {
46        let doc = match self {
47            Self::FunctionDefinition(n) => n.documentation.as_ref()?,
48            Self::VariableDeclaration(n) => n.documentation.as_ref()?,
49            Self::EventDefinition(n) => n.documentation.as_ref()?,
50            Self::ErrorDefinition(n) => n.documentation.as_ref()?,
51            Self::StructDefinition(n) => n.documentation.as_ref()?,
52            Self::EnumDefinition(n) => n.documentation.as_ref()?,
53            Self::ModifierDefinition(n) => n.documentation.as_ref()?,
54            _ => return None,
55        };
56        match doc {
57            super::Documentation::String(s) => Some(s.clone()),
58            super::Documentation::Structured(s) => Some(s.text.clone()),
59        }
60    }
61}
62
63/// An inheritance specifier (`is Base(arg1, arg2)`).
64#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
65#[serde(rename_all = "camelCase")]
66pub struct InheritanceSpecifier {
67    pub id: NodeID,
68    pub src: String,
69    pub base_name: IdentifierPath,
70    #[serde(default)]
71    pub arguments: Option<Vec<Expression>>,
72}
73
74/// A `using ... for ...` directive.
75#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
76#[serde(rename_all = "camelCase")]
77pub struct UsingForDirective {
78    pub id: NodeID,
79    pub src: String,
80    /// The type this directive applies to. `None` means `*` (all types).
81    #[serde(default)]
82    pub type_name: Option<TypeName>,
83    /// Library name (when `using Lib for Type`).
84    #[serde(default)]
85    pub library_name: Option<IdentifierPath>,
86    /// Function list (when `using { f, g } for Type`).
87    #[serde(default)]
88    pub function_list: Option<Vec<UsingForFunction>>,
89    /// Whether this is a file-level `using ... for ... global` directive.
90    #[serde(default)]
91    pub global: Option<bool>,
92}
93
94/// A struct definition.
95#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
96#[serde(rename_all = "camelCase")]
97pub struct StructDefinition {
98    pub id: NodeID,
99    pub src: String,
100    pub name: String,
101    #[serde(default)]
102    pub name_location: Option<String>,
103    #[serde(default)]
104    pub documentation: Option<Documentation>,
105    #[serde(default)]
106    pub visibility: Option<String>,
107    #[serde(default)]
108    pub members: Vec<VariableDeclaration>,
109    #[serde(default)]
110    pub scope: Option<NodeID>,
111    #[serde(default)]
112    pub canonical_name: Option<String>,
113}
114
115/// An enum definition.
116#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
117#[serde(rename_all = "camelCase")]
118pub struct EnumDefinition {
119    pub id: NodeID,
120    pub src: String,
121    pub name: String,
122    #[serde(default)]
123    pub name_location: Option<String>,
124    #[serde(default)]
125    pub documentation: Option<Documentation>,
126    #[serde(default)]
127    pub members: Vec<EnumValue>,
128    #[serde(default)]
129    pub canonical_name: Option<String>,
130}
131
132/// A single enum member value.
133#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
134#[serde(rename_all = "camelCase")]
135pub struct EnumValue {
136    pub id: NodeID,
137    pub src: String,
138    pub name: String,
139    #[serde(default)]
140    pub name_location: Option<String>,
141}
142
143/// A user-defined value type (`type MyUint is uint256`).
144#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
145#[serde(rename_all = "camelCase")]
146pub struct UserDefinedValueTypeDefinition {
147    pub id: NodeID,
148    pub src: String,
149    pub name: String,
150    #[serde(default)]
151    pub name_location: Option<String>,
152    pub underlying_type: TypeName,
153    #[serde(default)]
154    pub canonical_name: Option<String>,
155}
156
157/// A contract definition.
158#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq)]
159#[serde(rename_all = "camelCase")]
160pub struct ContractDefinition {
161    pub id: NodeID,
162    pub src: String,
163    pub name: String,
164    #[serde(default)]
165    pub name_location: Option<String>,
166    #[serde(default)]
167    pub documentation: Option<Documentation>,
168    pub contract_kind: ContractKind,
169    #[serde(rename = "abstract", default)]
170    pub is_abstract: Option<bool>,
171    #[serde(default)]
172    pub base_contracts: Vec<InheritanceSpecifier>,
173    #[serde(default)]
174    pub contract_dependencies: Vec<NodeID>,
175    #[serde(default)]
176    pub used_errors: Option<Vec<NodeID>>,
177    #[serde(default)]
178    pub used_events: Option<Vec<NodeID>>,
179    #[serde(default)]
180    pub nodes: Vec<ContractDefinitionNode>,
181    #[serde(default)]
182    pub scope: Option<NodeID>,
183    #[serde(default)]
184    pub fully_implemented: Option<bool>,
185    #[serde(default)]
186    pub linearized_base_contracts: Option<Vec<NodeID>>,
187    #[serde(default)]
188    pub canonical_name: Option<String>,
189}