Skip to main content

neo_devpack_solidity/solidity/
solidity_metadata.rs

1#[derive(Debug, Clone, Default)]
2pub struct SelectorRegistry {
3    /// Mapping of Solidity type name -> method name -> list of selectors (one per overload).
4    ///
5    /// This supports lowering expressions like `IERC20.transfer.selector` into a constant
6    /// `bytes4` value and allows recovering Neo method names from `.selector` expressions in
7    /// low-level EVM call shims (`abi.encodeWithSelector(...)`).
8    pub type_method_selectors:
9        std::collections::HashMap<String, std::collections::HashMap<String, Vec<[u8; 4]>>>,
10    /// Set of known Solidity interface type names visible to the compilation unit.
11    pub interface_types: std::collections::HashSet<String>,
12}
13
14#[derive(Debug, Clone)]
15pub struct ContractMetadata {
16    pub name: String,
17    pub is_abstract: bool,
18    /// Whether this contract was declared as an `interface`.
19    pub is_interface: bool,
20    /// Whether this contract was declared as a `library`.
21    pub is_library: bool,
22    pub methods: Vec<FunctionMetadata>,
23    pub events: Vec<EventMetadata>,
24    /// Declared custom `error` definitions (contract-level, file-level, and
25    /// inherited). Consumed by IR lowering to compute EVM custom-error
26    /// selectors from the DECLARED parameter types.
27    pub errors: Vec<ErrorMetadata>,
28    pub uses_storage: bool,
29    pub state_variables: Vec<StateVariableMetadata>,
30    pub structs: Vec<StructMetadata>,
31    pub enums: Vec<EnumMetadata>,
32    /// All contract/interface type names visible to this compilation unit.
33    ///
34    /// This is used during IR lowering to recognize Solidity-style contract casts
35    /// like `IERC20(token).transfer(...)` without accidentally treating unknown
36    /// function calls as casts.
37    pub contract_types: Vec<String>,
38    /// Registry of known function selectors for contract/interface types visible to this
39    /// compilation unit (shared across contracts via `Arc`).
40    pub selector_registry: std::sync::Arc<SelectorRegistry>,
41    /// Natspec documentation for the contract
42    pub documentation: NatspecDoc,
43    /// Whether this contract contains `using X for *` directives.
44    pub has_using_for_star: bool,
45    /// Whether this contract contains `using { f, g } for Y` directives.
46    pub has_using_function_list: bool,
47    /// Library names referenced by `using X for Y` directives.
48    pub using_for_libraries: Vec<String>,
49    /// Structured `using` directives used for type-aware member-call lowering.
50    pub using_directives: Vec<UsingDirectiveMetadata>,
51    /// Whether this contract contains `type X is Y` definitions.
52    pub has_type_definitions: bool,
53    /// User-defined value type aliases (`type X is Y`).
54    /// Maps type name to underlying Solidity type string.
55    pub type_aliases: std::collections::HashMap<String, String>,
56    /// Warnings collected during inheritance flattening (e.g. virtual/override checks).
57    pub flatten_warnings: Vec<String>,
58    /// Mapping from original method name to the renamed super-method name.
59    /// Populated during inheritance flattening so `super.method()` can resolve.
60    pub super_method_map: std::collections::HashMap<String, String>,
61}
62
63#[derive(Debug, Clone)]
64pub struct UsingDirectiveMetadata {
65    /// `None` means wildcard target (`for *`), otherwise normalized target type.
66    pub target_type: Option<String>,
67    /// Function-name allowlist for `using {f, g} for T`.
68    ///
69    /// `None` means library-form directive (`using Lib for T`) where all compatible
70    /// library functions are eligible.
71    pub function_names: Option<Vec<String>>,
72}
73
74#[derive(Debug, Clone)]
75pub struct FunctionMetadata {
76    pub name: String,
77    /// Neo entrypoint name. This may be mangled to disambiguate overloaded
78    /// Solidity functions because Neo ABI dispatches by name+arg count.
79    pub neo_name: String,
80    pub kind: FunctionKind,
81    pub parameters: Vec<ParameterMetadata>,
82    pub return_parameters: Vec<ParameterMetadata>,
83    pub state_mutability: StateMutability,
84    pub visibility: VisibilityKind,
85    pub offset: u32,
86    pub body: Option<Statement>,
87    pub selector: [u8; 4],
88    /// Whether this function is marked `virtual`.
89    pub is_virtual: bool,
90    /// Whether this function is marked `override`.
91    pub is_override: bool,
92    /// Natspec documentation for the function
93    pub documentation: NatspecDoc,
94    /// Task #114 — set during modifier expansion when at least one applied
95    /// modifier had an epilogue (statements after the `_;` placeholder).
96    /// The IR lowerer uses this to redirect `return expr;` in the expanded
97    /// body to synthetic slots + a jump past the epilogue so modifier tail
98    /// statements still run before the function actually returns.
99    pub had_modifier_epilogue: bool,
100}
101
102#[derive(Debug, Clone, Copy, PartialEq, Eq)]
103pub enum FunctionKind {
104    Constructor,
105    Regular,
106}
107
108#[derive(Debug, Clone)]
109pub struct ParameterMetadata {
110    pub name: Option<String>,
111    pub ty: String,
112    pub neo_type: Option<NeoType>,
113    pub storage: Option<String>,
114}
115
116#[derive(Debug, Clone)]
117pub struct EventMetadata {
118    pub name: String,
119    pub normalized_name: String,
120    pub parameters: Vec<EventParameter>,
121    /// `true` when the event was declared `anonymous` in Solidity source.
122    /// Anonymous events suppress the `keccak256(signature)` topic0 per the
123    /// EVM ABI; the IR lowering reads this to skip the topic0 prepend.
124    pub anonymous: bool,
125}
126
127#[derive(Debug, Clone)]
128pub struct EventParameter {
129    pub name: Option<String>,
130    pub ty: String,
131    pub indexed: bool,
132    pub neo_type: Option<NeoType>,
133}
134
135/// Declared custom `error` definition.
136#[derive(Debug, Clone)]
137pub struct ErrorMetadata {
138    pub name: String,
139    /// Declared parameters in declaration order.
140    pub parameters: Vec<ErrorParameterMetadata>,
141}
142
143/// One declared parameter of a custom `error`.
144#[derive(Debug, Clone)]
145pub struct ErrorParameterMetadata {
146    pub name: Option<String>,
147    /// Raw Solidity type string as written in the declaration (canonicalized
148    /// against enums/structs in scope at IR-lowering time).
149    pub ty: String,
150}
151
152#[derive(Debug, Clone)]
153pub struct StateVariableMetadata {
154    pub name: Option<String>,
155    pub ty: String,
156    pub is_constant: bool,
157    pub is_immutable: bool,
158    pub visibility: Option<String>,
159    pub neo_type: Option<NeoType>,
160    pub has_initializer: bool,
161    pub initializer: Option<Expression>,
162}
163
164#[derive(Debug, Clone)]
165pub struct StructMetadata {
166    pub name: String,
167    pub fields: Vec<StructFieldMetadata>,
168}
169
170#[derive(Debug, Clone)]
171pub struct StructFieldMetadata {
172    pub name: String,
173    pub ty: String,
174}
175
176#[derive(Debug, Clone)]
177pub struct EnumMetadata {
178    pub name: String,
179    pub values: Vec<String>,
180}
181
182#[derive(Debug, Clone, Copy, PartialEq, Eq)]
183pub enum StateMutability {
184    Pure,
185    View,
186    NonPayable,
187    Payable,
188}
189
190impl StateMutability {
191    pub fn is_safe(self) -> bool {
192        matches!(self, StateMutability::Pure | StateMutability::View)
193    }
194}
195
196#[derive(Debug, Clone, Copy, PartialEq, Eq)]
197pub enum DiagnosticSeverity {
198    Warning,
199    Error,
200}
201
202#[derive(Debug, Clone)]
203pub struct Diagnostic {
204    pub severity: DiagnosticSeverity,
205    pub message: String,
206    pub code: Option<String>,
207    pub suggestion: Option<String>,
208}
209
210impl Diagnostic {
211    /// Create a warning diagnostic.
212    pub fn warning(message: impl Into<String>) -> Self {
213        Self {
214            severity: DiagnosticSeverity::Warning,
215            message: message.into(),
216            code: None,
217            suggestion: None,
218        }
219    }
220
221    /// Create an error diagnostic.
222    pub fn error(message: impl Into<String>) -> Self {
223        Self {
224            severity: DiagnosticSeverity::Error,
225            message: message.into(),
226            code: None,
227            suggestion: None,
228        }
229    }
230
231    /// Attach a diagnostic code (e.g. "W101", "E042").
232    pub fn with_code(mut self, code: impl Into<String>) -> Self {
233        self.code = Some(code.into());
234        self
235    }
236
237    /// Attach an actionable fix suggestion.
238    pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
239        self.suggestion = Some(suggestion.into());
240        self
241    }
242}