parent
5bc9ee73b2
commit
d5ebff42e4
|
@ -16,9 +16,9 @@ use crate::{
|
||||||
BytecodeOutputSelection, ContractOutputSelection, EvmOutputSelection,
|
BytecodeOutputSelection, ContractOutputSelection, EvmOutputSelection,
|
||||||
EwasmOutputSelection,
|
EwasmOutputSelection,
|
||||||
},
|
},
|
||||||
Ast, CompactContractBytecodeCow, DevDoc, Evm, Ewasm, FunctionDebugData, GasEstimates,
|
CompactContractBytecodeCow, DevDoc, Evm, Ewasm, FunctionDebugData, GasEstimates,
|
||||||
GeneratedSource, LosslessAbi, LosslessMetadata, Metadata, Offsets, Settings, StorageLayout,
|
GeneratedSource, LosslessAbi, LosslessMetadata, Metadata, Offsets, Settings, SourceUnit,
|
||||||
UserDoc,
|
StorageLayout, UserDoc,
|
||||||
},
|
},
|
||||||
sources::VersionedSourceFile,
|
sources::VersionedSourceFile,
|
||||||
ArtifactOutput, SolcConfig, SolcError, SourceFile,
|
ArtifactOutput, SolcConfig, SolcError, SourceFile,
|
||||||
|
@ -68,7 +68,7 @@ pub struct ConfigurableContractArtifact {
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub ewasm: Option<Ewasm>,
|
pub ewasm: Option<Ewasm>,
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub ast: Option<Ast>,
|
pub ast: Option<SourceUnit>,
|
||||||
/// The identifier of the source file
|
/// The identifier of the source file
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||||
pub id: Option<u32>,
|
pub id: Option<u32>,
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/// Macro that expands to a struct with common AST node fields.
|
||||||
|
macro_rules! ast_node {
|
||||||
|
(
|
||||||
|
$(#[$struct_meta:meta])*
|
||||||
|
struct $name:ident {
|
||||||
|
$(
|
||||||
|
$(#[$field_meta:meta])*
|
||||||
|
$field:ident: $ty:ty
|
||||||
|
),* $(,)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
$(#[$struct_meta])*
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct $name {
|
||||||
|
pub id: usize,
|
||||||
|
#[serde(with = "serde_helpers::display_from_str")]
|
||||||
|
pub src: SourceLocation,
|
||||||
|
$(
|
||||||
|
$(#[$field_meta])*
|
||||||
|
pub $field: $ty
|
||||||
|
),*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A macro that expands to a struct with common expression node fields.
|
||||||
|
macro_rules! expr_node {
|
||||||
|
(
|
||||||
|
$(#[$struct_meta:meta])*
|
||||||
|
struct $name:ident {
|
||||||
|
$(
|
||||||
|
$(#[$field_meta:meta])*
|
||||||
|
$field:ident: $ty:ty
|
||||||
|
),* $(,)*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
ast_node!(
|
||||||
|
$(#[$struct_meta])*
|
||||||
|
struct $name {
|
||||||
|
argument_types: Vec<TypeDescriptions>,
|
||||||
|
is_constant: bool,
|
||||||
|
is_l_value: bool,
|
||||||
|
is_pure: bool,
|
||||||
|
l_value_requested: bool,
|
||||||
|
type_descriptions: TypeDescriptions,
|
||||||
|
$(
|
||||||
|
$(#[$field_meta])*
|
||||||
|
$field: $ty
|
||||||
|
),*
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) use ast_node;
|
||||||
|
pub(crate) use expr_node;
|
|
@ -1,63 +1,5 @@
|
||||||
//! Bindings for solc's `ast` output field
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::{fmt, fmt::Write, str::FromStr};
|
||||||
use crate::artifacts::serde_helpers;
|
|
||||||
use serde::{de::DeserializeOwned, Deserialize, Serialize};
|
|
||||||
use std::{collections::BTreeMap, fmt, fmt::Write, str::FromStr};
|
|
||||||
|
|
||||||
/// Represents the AST field in the solc output
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
||||||
pub struct Ast {
|
|
||||||
#[serde(rename = "absolutePath")]
|
|
||||||
pub absolute_path: String,
|
|
||||||
pub id: usize,
|
|
||||||
#[serde(default, rename = "exportedSymbols")]
|
|
||||||
pub exported_symbols: BTreeMap<String, Vec<usize>>,
|
|
||||||
#[serde(rename = "nodeType")]
|
|
||||||
pub node_type: NodeType,
|
|
||||||
#[serde(with = "serde_helpers::display_from_str")]
|
|
||||||
pub src: SourceLocation,
|
|
||||||
#[serde(default)]
|
|
||||||
pub nodes: Vec<Node>,
|
|
||||||
|
|
||||||
/// Node attributes that were not deserialized.
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub other: BTreeMap<String, serde_json::Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
|
||||||
pub struct Node {
|
|
||||||
/// The node ID.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub id: Option<usize>,
|
|
||||||
|
|
||||||
/// The node type.
|
|
||||||
#[serde(rename = "nodeType")]
|
|
||||||
pub node_type: NodeType,
|
|
||||||
|
|
||||||
/// The location of the node in the source file.
|
|
||||||
#[serde(with = "serde_helpers::display_from_str")]
|
|
||||||
pub src: SourceLocation,
|
|
||||||
|
|
||||||
/// Child nodes for some node types.
|
|
||||||
#[serde(default)]
|
|
||||||
pub nodes: Vec<Node>,
|
|
||||||
|
|
||||||
/// Body node for some node types.
|
|
||||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
|
||||||
pub body: Option<Box<Node>>,
|
|
||||||
|
|
||||||
/// Node attributes that were not deserialized.
|
|
||||||
#[serde(flatten)]
|
|
||||||
pub other: BTreeMap<String, serde_json::Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Node {
|
|
||||||
/// Deserialize a serialized node attribute.
|
|
||||||
pub fn attribute<D: DeserializeOwned>(&self, key: impl AsRef<str>) -> Option<D> {
|
|
||||||
// TODO: Can we avoid this clone?
|
|
||||||
self.other.get(key.as_ref()).and_then(|v| serde_json::from_value(v.clone()).ok())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Represents the source location of a node: `<start byte>:<length>:<source index>`.
|
/// Represents the source location of a node: `<start byte>:<length>:<source index>`.
|
||||||
///
|
///
|
||||||
|
@ -119,8 +61,7 @@ impl fmt::Display for SourceLocation {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum NodeType {
|
pub enum Expression {
|
||||||
// Expressions
|
|
||||||
Assignment,
|
Assignment,
|
||||||
BinaryOperation,
|
BinaryOperation,
|
||||||
Conditional,
|
Conditional,
|
||||||
|
@ -135,8 +76,50 @@ pub enum NodeType {
|
||||||
NewExpression,
|
NewExpression,
|
||||||
TupleExpression,
|
TupleExpression,
|
||||||
UnaryOperation,
|
UnaryOperation,
|
||||||
|
}
|
||||||
|
|
||||||
// Statements
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum StateMutability {
|
||||||
|
Payable,
|
||||||
|
Pure,
|
||||||
|
Nonpayable,
|
||||||
|
View,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum TypeName {
|
||||||
|
ArrayTypeName,
|
||||||
|
ElementaryTypeName,
|
||||||
|
FunctionTypeName,
|
||||||
|
Mapping,
|
||||||
|
UserDefinedTypeName,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum Mutability {
|
||||||
|
Mutable,
|
||||||
|
Immutable,
|
||||||
|
Constant,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum StorageLocation {
|
||||||
|
Calldata,
|
||||||
|
Default,
|
||||||
|
Memory,
|
||||||
|
Storage,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum Visibility {
|
||||||
|
External,
|
||||||
|
Public,
|
||||||
|
Internal,
|
||||||
|
Private,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum Statement {
|
||||||
Block,
|
Block,
|
||||||
Break,
|
Break,
|
||||||
Continue,
|
Continue,
|
||||||
|
@ -152,10 +135,11 @@ pub enum NodeType {
|
||||||
TryStatement,
|
TryStatement,
|
||||||
UncheckedBlock,
|
UncheckedBlock,
|
||||||
VariableDeclarationStatement,
|
VariableDeclarationStatement,
|
||||||
VariableDeclaration,
|
|
||||||
WhileStatement,
|
WhileStatement,
|
||||||
|
}
|
||||||
|
|
||||||
// Yul statements
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum YulStatement {
|
||||||
YulAssignment,
|
YulAssignment,
|
||||||
YulBlock,
|
YulBlock,
|
||||||
YulBreak,
|
YulBreak,
|
||||||
|
@ -167,51 +151,17 @@ pub enum NodeType {
|
||||||
YulIf,
|
YulIf,
|
||||||
YulSwitch,
|
YulSwitch,
|
||||||
YulVariableDeclaration,
|
YulVariableDeclaration,
|
||||||
|
}
|
||||||
|
|
||||||
// Yul expressions
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum YulExpression {
|
||||||
YulFunctionCall,
|
YulFunctionCall,
|
||||||
YulIdentifier,
|
YulIdentifier,
|
||||||
YulLiteral,
|
YulLiteral,
|
||||||
|
}
|
||||||
|
|
||||||
// Yul literals
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum YulLiteral {
|
||||||
YulLiteralValue,
|
YulLiteralValue,
|
||||||
YulHexValue,
|
YulLiteralHexValue,
|
||||||
|
|
||||||
// Definitions
|
|
||||||
ContractDefinition,
|
|
||||||
FunctionDefinition,
|
|
||||||
EventDefinition,
|
|
||||||
ErrorDefinition,
|
|
||||||
ModifierDefinition,
|
|
||||||
StructDefinition,
|
|
||||||
EnumDefinition,
|
|
||||||
UserDefinedValueTypeDefinition,
|
|
||||||
|
|
||||||
// Directives
|
|
||||||
PragmaDirective,
|
|
||||||
ImportDirective,
|
|
||||||
UsingForDirective,
|
|
||||||
|
|
||||||
// Misc
|
|
||||||
SourceUnit,
|
|
||||||
InheritanceSpecifier,
|
|
||||||
ElementaryTypeName,
|
|
||||||
FunctionTypeName,
|
|
||||||
ParameterList,
|
|
||||||
TryCatchClause,
|
|
||||||
ModifierInvocation,
|
|
||||||
|
|
||||||
/// An unknown AST node type.
|
|
||||||
Other(String),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn can_parse_ast() {
|
|
||||||
let ast = include_str!("../../test-data/ast/ast-erc4626.json");
|
|
||||||
let _ast: Ast = serde_json::from_str(ast).unwrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,248 @@
|
||||||
|
//! Bindings for solc's `ast` output field
|
||||||
|
mod macros;
|
||||||
|
mod misc;
|
||||||
|
|
||||||
|
pub use misc::*;
|
||||||
|
pub mod util;
|
||||||
|
pub mod visitor;
|
||||||
|
|
||||||
|
use crate::artifacts::serde_helpers;
|
||||||
|
use macros::{ast_node, expr_node};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
// TODO: Node ID
|
||||||
|
|
||||||
|
ast_node!(
|
||||||
|
/// The root node of a Solidity AST.
|
||||||
|
struct SourceUnit {
|
||||||
|
#[serde(rename = "absolutePath")]
|
||||||
|
absolute_path: String,
|
||||||
|
#[serde(default, rename = "exportedSymbols")]
|
||||||
|
exported_symbols: BTreeMap<String, Vec<usize>>,
|
||||||
|
license: Option<String>,
|
||||||
|
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||||||
|
nodes: Vec<SourceUnitPart>,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum SourceUnitPart {
|
||||||
|
PragmaDirective,
|
||||||
|
ImportDirective,
|
||||||
|
UsingForDirective,
|
||||||
|
VariableDeclaration,
|
||||||
|
EnumDefinition,
|
||||||
|
ErrorDefinition,
|
||||||
|
FunctionDefinition,
|
||||||
|
StructDefinition,
|
||||||
|
UserDefinedValueTypeDefinition,
|
||||||
|
ContractDefinition,
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_node!(
|
||||||
|
struct ContractDefinition {
|
||||||
|
name: String,
|
||||||
|
name_location: Option<String>,
|
||||||
|
is_abstract: bool,
|
||||||
|
base_contracts: Vec<InheritanceSpecifier>,
|
||||||
|
canonical_name: Option<String>,
|
||||||
|
contract_dependencies: Vec<usize>,
|
||||||
|
kind: ContractKind,
|
||||||
|
documentation: Option<StructuredDocumentation>,
|
||||||
|
fully_implemented: bool,
|
||||||
|
linearized_base_contracts: Vec<usize>,
|
||||||
|
nodes: Vec<ContractDefinitionPart>,
|
||||||
|
scope: usize,
|
||||||
|
used_errors: Vec<usize>,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum ContractKind {
|
||||||
|
Contract,
|
||||||
|
Interface,
|
||||||
|
Library,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum ContractDefinitionPart {
|
||||||
|
EnumDefinition,
|
||||||
|
ErrorDefinition,
|
||||||
|
EventDefinition,
|
||||||
|
FunctionDefinition,
|
||||||
|
ModifierDefinition,
|
||||||
|
StructDefinition,
|
||||||
|
UserDefinedValueTypeDefinition,
|
||||||
|
UsingForDirective,
|
||||||
|
VariableDeclaration,
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_node!(
|
||||||
|
struct InheritanceSpecifier {
|
||||||
|
arguments: Vec<Expression>,
|
||||||
|
base_name: UserDefinedTypeNameOrIdentifierPath,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// TODO: Better name
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum UserDefinedTypeNameOrIdentifierPath {
|
||||||
|
UserDefinedTypeName,
|
||||||
|
IdentifierPath,
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_node!(
|
||||||
|
struct Assignment {
|
||||||
|
lhs: Expression,
|
||||||
|
operator: AssignmentOperator,
|
||||||
|
rhs: Expression,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum AssignmentOperator {
|
||||||
|
/// =
|
||||||
|
Assign,
|
||||||
|
/// +=
|
||||||
|
AddAssign,
|
||||||
|
/// -=
|
||||||
|
SubAssign,
|
||||||
|
/// *=
|
||||||
|
MulAssign,
|
||||||
|
/// /=
|
||||||
|
DivAssign,
|
||||||
|
/// %=
|
||||||
|
ModAssign,
|
||||||
|
/// |=
|
||||||
|
OrAssign,
|
||||||
|
/// &=
|
||||||
|
AndAssign,
|
||||||
|
/// ^=
|
||||||
|
XorAssign,
|
||||||
|
/// >>=
|
||||||
|
ShrAssign,
|
||||||
|
/// <<=
|
||||||
|
ShlAssign,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct TypeDescriptions {
|
||||||
|
pub type_identifier: Option<String>,
|
||||||
|
pub type_string: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
ast_node!(
|
||||||
|
struct BinaryOperation {
|
||||||
|
common_type: TypeDescriptions,
|
||||||
|
lhs: Expression,
|
||||||
|
operator: BinaryOperator,
|
||||||
|
rhs: Expression,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum BinaryOperator {
|
||||||
|
/// +
|
||||||
|
Add,
|
||||||
|
/// -
|
||||||
|
Sub,
|
||||||
|
/// *
|
||||||
|
Mul,
|
||||||
|
/// /
|
||||||
|
Div,
|
||||||
|
/// %
|
||||||
|
Mod,
|
||||||
|
/// **
|
||||||
|
Pow,
|
||||||
|
/// &&
|
||||||
|
And,
|
||||||
|
/// ||
|
||||||
|
Or,
|
||||||
|
/// !=
|
||||||
|
NotEqual,
|
||||||
|
/// ==
|
||||||
|
Equal,
|
||||||
|
/// <
|
||||||
|
LessThan,
|
||||||
|
/// <=
|
||||||
|
LessThanOrEqual,
|
||||||
|
/// >
|
||||||
|
GreaterThan,
|
||||||
|
/// >=
|
||||||
|
GreaterThanOrEqual,
|
||||||
|
/// ^
|
||||||
|
Xor,
|
||||||
|
/// &
|
||||||
|
BitAnd,
|
||||||
|
/// |
|
||||||
|
BitOr,
|
||||||
|
/// <<
|
||||||
|
Shl,
|
||||||
|
/// >>
|
||||||
|
Shr,
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_node!(
|
||||||
|
struct Conditional {
|
||||||
|
condition: Expression,
|
||||||
|
false_expression: Expression,
|
||||||
|
true_expression: Expression,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expr_node!(
|
||||||
|
struct ElementaryTypeNameExpression {
|
||||||
|
type_name: ElementaryTypeName,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ast_node!(
|
||||||
|
struct ElementaryTypeName {
|
||||||
|
type_descriptions: TypeDescriptions,
|
||||||
|
name: String,
|
||||||
|
state_mutability: Option<StateMutability>,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expr_node!(
|
||||||
|
struct FunctionCall {
|
||||||
|
arguments: Vec<Expression>,
|
||||||
|
expression: Expression,
|
||||||
|
kind: FunctionCallKind,
|
||||||
|
names: Vec<String>,
|
||||||
|
try_call: bool,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub enum FunctionCallKind {
|
||||||
|
FunctionCall,
|
||||||
|
TypeConversion,
|
||||||
|
StructConstructorCall,
|
||||||
|
}
|
||||||
|
|
||||||
|
expr_node!(
|
||||||
|
struct FunctionCallOptions {
|
||||||
|
expression: Expression,
|
||||||
|
names: Vec<String>,
|
||||||
|
options: Vec<Expression>,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ast_node!(
|
||||||
|
struct StructuredDocumentation {
|
||||||
|
text: String,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn can_parse_ast() {
|
||||||
|
let ast = include_str!("../../test-data/ast/ast-erc4626.json");
|
||||||
|
let _ast: SourceUnit = serde_json::from_str(ast).unwrap();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -1835,7 +1835,7 @@ pub struct SecondarySourceLocation {
|
||||||
pub struct SourceFile {
|
pub struct SourceFile {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
#[serde(default, with = "serde_helpers::empty_json_object_opt")]
|
#[serde(default, with = "serde_helpers::empty_json_object_opt")]
|
||||||
pub ast: Option<Ast>,
|
pub ast: Option<SourceUnit>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// === impl SourceFile ===
|
// === impl SourceFile ===
|
||||||
|
@ -1846,7 +1846,7 @@ impl SourceFile {
|
||||||
pub fn contains_contract_definition(&self) -> bool {
|
pub fn contains_contract_definition(&self) -> bool {
|
||||||
if let Some(ref ast) = self.ast {
|
if let Some(ref ast) = self.ast {
|
||||||
// contract definitions are only allowed at the source-unit level <https://docs.soliditylang.org/en/latest/grammar.html>
|
// contract definitions are only allowed at the source-unit level <https://docs.soliditylang.org/en/latest/grammar.html>
|
||||||
return ast.nodes.iter().any(|node| node.node_type == NodeType::ContractDefinition)
|
return ast.nodes.iter().any(|node| matches!(node, SourceUnitPart::ContractDefinition))
|
||||||
// abstract contract, interfaces: ContractDefinition
|
// abstract contract, interfaces: ContractDefinition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue