@@ -118,7 +118,7 @@ impl fmt::Display for SourceLocation {
118118 }
119119}
120120
121- #[ derive( Clone , Debug , PartialEq , Eq , Serialize , Deserialize ) ]
121+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
122122pub enum NodeType {
123123 // Expressions
124124 Assignment ,
@@ -210,6 +210,169 @@ pub enum NodeType {
210210 Other ( String ) ,
211211}
212212
213+ impl serde:: Serialize for NodeType {
214+ fn serialize < S > ( & self , serializer : S ) -> Result < S :: Ok , S :: Error >
215+ where
216+ S : serde:: Serializer ,
217+ {
218+ match self {
219+ NodeType :: Assignment => serializer. serialize_str ( "Assignment" ) ,
220+ NodeType :: BinaryOperation => serializer. serialize_str ( "BinaryOperation" ) ,
221+ NodeType :: Conditional => serializer. serialize_str ( "Conditional" ) ,
222+ NodeType :: ElementaryTypeNameExpression => {
223+ serializer. serialize_str ( "ElementaryTypeNameExpression" )
224+ }
225+ NodeType :: FunctionCall => serializer. serialize_str ( "FunctionCall" ) ,
226+ NodeType :: FunctionCallOptions => serializer. serialize_str ( "FunctionCallOptions" ) ,
227+ NodeType :: Identifier => serializer. serialize_str ( "Identifier" ) ,
228+ NodeType :: IndexAccess => serializer. serialize_str ( "IndexAccess" ) ,
229+ NodeType :: IndexRangeAccess => serializer. serialize_str ( "IndexRangeAccess" ) ,
230+ NodeType :: Literal => serializer. serialize_str ( "Literal" ) ,
231+ NodeType :: MemberAccess => serializer. serialize_str ( "MemberAccess" ) ,
232+ NodeType :: NewExpression => serializer. serialize_str ( "NewExpression" ) ,
233+ NodeType :: TupleExpression => serializer. serialize_str ( "TupleExpression" ) ,
234+ NodeType :: UnaryOperation => serializer. serialize_str ( "UnaryOperation" ) ,
235+ NodeType :: Block => serializer. serialize_str ( "Block" ) ,
236+ NodeType :: Break => serializer. serialize_str ( "Break" ) ,
237+ NodeType :: Continue => serializer. serialize_str ( "Continue" ) ,
238+ NodeType :: DoWhileStatement => serializer. serialize_str ( "DoWhileStatement" ) ,
239+ NodeType :: EmitStatement => serializer. serialize_str ( "EmitStatement" ) ,
240+ NodeType :: ExpressionStatement => serializer. serialize_str ( "ExpressionStatement" ) ,
241+ NodeType :: ForStatement => serializer. serialize_str ( "ForStatement" ) ,
242+ NodeType :: IfStatement => serializer. serialize_str ( "IfStatement" ) ,
243+ NodeType :: InlineAssembly => serializer. serialize_str ( "InlineAssembly" ) ,
244+ NodeType :: PlaceholderStatement => serializer. serialize_str ( "PlaceholderStatement" ) ,
245+ NodeType :: Return => serializer. serialize_str ( "Return" ) ,
246+ NodeType :: RevertStatement => serializer. serialize_str ( "RevertStatement" ) ,
247+ NodeType :: TryStatement => serializer. serialize_str ( "TryStatement" ) ,
248+ NodeType :: UncheckedBlock => serializer. serialize_str ( "UncheckedBlock" ) ,
249+ NodeType :: VariableDeclarationStatement => {
250+ serializer. serialize_str ( "VariableDeclarationStatement" )
251+ }
252+ NodeType :: VariableDeclaration => serializer. serialize_str ( "VariableDeclaration" ) ,
253+ NodeType :: WhileStatement => serializer. serialize_str ( "WhileStatement" ) ,
254+ NodeType :: YulAssignment => serializer. serialize_str ( "YulAssignment" ) ,
255+ NodeType :: YulBlock => serializer. serialize_str ( "YulBlock" ) ,
256+ NodeType :: YulBreak => serializer. serialize_str ( "YulBreak" ) ,
257+ NodeType :: YulCase => serializer. serialize_str ( "YulCase" ) ,
258+ NodeType :: YulContinue => serializer. serialize_str ( "YulContinue" ) ,
259+ NodeType :: YulExpressionStatement => serializer. serialize_str ( "YulExpressionStatement" ) ,
260+ NodeType :: YulLeave => serializer. serialize_str ( "YulLeave" ) ,
261+ NodeType :: YulForLoop => serializer. serialize_str ( "YulForLoop" ) ,
262+ NodeType :: YulFunctionDefinition => serializer. serialize_str ( "YulFunctionDefinition" ) ,
263+ NodeType :: YulIf => serializer. serialize_str ( "YulIf" ) ,
264+ NodeType :: YulSwitch => serializer. serialize_str ( "YulSwitch" ) ,
265+ NodeType :: YulVariableDeclaration => serializer. serialize_str ( "YulVariableDeclaration" ) ,
266+ NodeType :: YulFunctionCall => serializer. serialize_str ( "YulFunctionCall" ) ,
267+ NodeType :: YulIdentifier => serializer. serialize_str ( "YulIdentifier" ) ,
268+ NodeType :: YulLiteral => serializer. serialize_str ( "YulLiteral" ) ,
269+ NodeType :: YulLiteralValue => serializer. serialize_str ( "YulLiteralValue" ) ,
270+ NodeType :: YulHexValue => serializer. serialize_str ( "YulHexValue" ) ,
271+ NodeType :: YulTypedName => serializer. serialize_str ( "YulTypedName" ) ,
272+ NodeType :: ContractDefinition => serializer. serialize_str ( "ContractDefinition" ) ,
273+ NodeType :: FunctionDefinition => serializer. serialize_str ( "FunctionDefinition" ) ,
274+ NodeType :: EventDefinition => serializer. serialize_str ( "EventDefinition" ) ,
275+ NodeType :: ErrorDefinition => serializer. serialize_str ( "ErrorDefinition" ) ,
276+ NodeType :: ModifierDefinition => serializer. serialize_str ( "ModifierDefinition" ) ,
277+ NodeType :: StructDefinition => serializer. serialize_str ( "StructDefinition" ) ,
278+ NodeType :: EnumDefinition => serializer. serialize_str ( "EnumDefinition" ) ,
279+ NodeType :: UserDefinedValueTypeDefinition => {
280+ serializer. serialize_str ( "UserDefinedValueTypeDefinition" )
281+ }
282+ NodeType :: PragmaDirective => serializer. serialize_str ( "PragmaDirective" ) ,
283+ NodeType :: ImportDirective => serializer. serialize_str ( "ImportDirective" ) ,
284+ NodeType :: UsingForDirective => serializer. serialize_str ( "UsingForDirective" ) ,
285+ NodeType :: SourceUnit => serializer. serialize_str ( "SourceUnit" ) ,
286+ NodeType :: InheritanceSpecifier => serializer. serialize_str ( "InheritanceSpecifier" ) ,
287+ NodeType :: ElementaryTypeName => serializer. serialize_str ( "ElementaryTypeName" ) ,
288+ NodeType :: FunctionTypeName => serializer. serialize_str ( "FunctionTypeName" ) ,
289+ NodeType :: ParameterList => serializer. serialize_str ( "ParameterList" ) ,
290+ NodeType :: TryCatchClause => serializer. serialize_str ( "TryCatchClause" ) ,
291+ NodeType :: ModifierInvocation => serializer. serialize_str ( "ModifierInvocation" ) ,
292+ NodeType :: Other ( s) => serializer. serialize_str ( s) ,
293+ }
294+ }
295+ }
296+
297+ impl < ' de > serde:: Deserialize < ' de > for NodeType {
298+ fn deserialize < D > ( deserializer : D ) -> Result < Self , D :: Error >
299+ where
300+ D : serde:: Deserializer < ' de > ,
301+ {
302+ let s = String :: deserialize ( deserializer) ?;
303+ Ok ( match s. as_str ( ) {
304+ "Assignment" => NodeType :: Assignment ,
305+ "BinaryOperation" => NodeType :: BinaryOperation ,
306+ "Conditional" => NodeType :: Conditional ,
307+ "ElementaryTypeNameExpression" => NodeType :: ElementaryTypeNameExpression ,
308+ "FunctionCall" => NodeType :: FunctionCall ,
309+ "FunctionCallOptions" => NodeType :: FunctionCallOptions ,
310+ "Identifier" => NodeType :: Identifier ,
311+ "IndexAccess" => NodeType :: IndexAccess ,
312+ "IndexRangeAccess" => NodeType :: IndexRangeAccess ,
313+ "Literal" => NodeType :: Literal ,
314+ "MemberAccess" => NodeType :: MemberAccess ,
315+ "NewExpression" => NodeType :: NewExpression ,
316+ "TupleExpression" => NodeType :: TupleExpression ,
317+ "UnaryOperation" => NodeType :: UnaryOperation ,
318+ "Block" => NodeType :: Block ,
319+ "Break" => NodeType :: Break ,
320+ "Continue" => NodeType :: Continue ,
321+ "DoWhileStatement" => NodeType :: DoWhileStatement ,
322+ "EmitStatement" => NodeType :: EmitStatement ,
323+ "ExpressionStatement" => NodeType :: ExpressionStatement ,
324+ "ForStatement" => NodeType :: ForStatement ,
325+ "IfStatement" => NodeType :: IfStatement ,
326+ "InlineAssembly" => NodeType :: InlineAssembly ,
327+ "PlaceholderStatement" => NodeType :: PlaceholderStatement ,
328+ "Return" => NodeType :: Return ,
329+ "RevertStatement" => NodeType :: RevertStatement ,
330+ "TryStatement" => NodeType :: TryStatement ,
331+ "UncheckedBlock" => NodeType :: UncheckedBlock ,
332+ "VariableDeclarationStatement" => NodeType :: VariableDeclarationStatement ,
333+ "VariableDeclaration" => NodeType :: VariableDeclaration ,
334+ "WhileStatement" => NodeType :: WhileStatement ,
335+ "YulAssignment" => NodeType :: YulAssignment ,
336+ "YulBlock" => NodeType :: YulBlock ,
337+ "YulBreak" => NodeType :: YulBreak ,
338+ "YulCase" => NodeType :: YulCase ,
339+ "YulContinue" => NodeType :: YulContinue ,
340+ "YulExpressionStatement" => NodeType :: YulExpressionStatement ,
341+ "YulLeave" => NodeType :: YulLeave ,
342+ "YulForLoop" => NodeType :: YulForLoop ,
343+ "YulFunctionDefinition" => NodeType :: YulFunctionDefinition ,
344+ "YulIf" => NodeType :: YulIf ,
345+ "YulSwitch" => NodeType :: YulSwitch ,
346+ "YulVariableDeclaration" => NodeType :: YulVariableDeclaration ,
347+ "YulFunctionCall" => NodeType :: YulFunctionCall ,
348+ "YulIdentifier" => NodeType :: YulIdentifier ,
349+ "YulLiteral" => NodeType :: YulLiteral ,
350+ "YulLiteralValue" => NodeType :: YulLiteralValue ,
351+ "YulHexValue" => NodeType :: YulHexValue ,
352+ "YulTypedName" => NodeType :: YulTypedName ,
353+ "ContractDefinition" => NodeType :: ContractDefinition ,
354+ "FunctionDefinition" => NodeType :: FunctionDefinition ,
355+ "EventDefinition" => NodeType :: EventDefinition ,
356+ "ErrorDefinition" => NodeType :: ErrorDefinition ,
357+ "ModifierDefinition" => NodeType :: ModifierDefinition ,
358+ "StructDefinition" => NodeType :: StructDefinition ,
359+ "EnumDefinition" => NodeType :: EnumDefinition ,
360+ "UserDefinedValueTypeDefinition" => NodeType :: UserDefinedValueTypeDefinition ,
361+ "PragmaDirective" => NodeType :: PragmaDirective ,
362+ "ImportDirective" => NodeType :: ImportDirective ,
363+ "UsingForDirective" => NodeType :: UsingForDirective ,
364+ "SourceUnit" => NodeType :: SourceUnit ,
365+ "InheritanceSpecifier" => NodeType :: InheritanceSpecifier ,
366+ "ElementaryTypeName" => NodeType :: ElementaryTypeName ,
367+ "FunctionTypeName" => NodeType :: FunctionTypeName ,
368+ "ParameterList" => NodeType :: ParameterList ,
369+ "TryCatchClause" => NodeType :: TryCatchClause ,
370+ "ModifierInvocation" => NodeType :: ModifierInvocation ,
371+ _ => NodeType :: Other ( s) ,
372+ } )
373+ }
374+ }
375+
213376#[ cfg( test) ]
214377mod tests {
215378 use super :: * ;
@@ -219,4 +382,97 @@ mod tests {
219382 let ast = include_str ! ( "../../../../../test-data/ast/ast-erc4626.json" ) ;
220383 let _ast: Ast = serde_json:: from_str ( ast) . unwrap ( ) ;
221384 }
385+
386+ #[ test]
387+ fn test_unknown_node_type_deserialization ( ) {
388+ // Test that unknown node types are properly handled with the Other variant
389+ let json = r#"{"nodeType": "SomeUnknownNodeType"}"# ;
390+ let parsed: serde_json:: Value = serde_json:: from_str ( json) . unwrap ( ) ;
391+ let node_type: NodeType = serde_json:: from_value ( parsed[ "nodeType" ] . clone ( ) ) . unwrap ( ) ;
392+ assert_eq ! ( node_type, NodeType :: Other ( "SomeUnknownNodeType" . to_string( ) ) ) ;
393+ }
394+
395+ #[ test]
396+ fn test_known_node_type_deserialization ( ) {
397+ // Test that known node types still work properly
398+ let json = r#"{"nodeType": "Assignment"}"# ;
399+ let parsed: serde_json:: Value = serde_json:: from_str ( json) . unwrap ( ) ;
400+ let node_type: NodeType = serde_json:: from_value ( parsed[ "nodeType" ] . clone ( ) ) . unwrap ( ) ;
401+ assert_eq ! ( node_type, NodeType :: Assignment ) ;
402+ }
403+
404+ #[ test]
405+ fn test_node_type_serialization ( ) {
406+ // Test that serialization works correctly for both known and unknown node types
407+ let known = NodeType :: Assignment ;
408+ let unknown = NodeType :: Other ( "SomeUnknownNodeType" . to_string ( ) ) ;
409+
410+ let known_json = serde_json:: to_string ( & known) . unwrap ( ) ;
411+ let unknown_json = serde_json:: to_string ( & unknown) . unwrap ( ) ;
412+
413+ assert_eq ! ( known_json, r#""Assignment""# ) ;
414+ assert_eq ! ( unknown_json, r#""SomeUnknownNodeType""# ) ;
415+ }
416+
417+ #[ test]
418+ fn test_node_type_roundtrip_serialization ( ) {
419+ // Test roundtrip serialization for all known node types to ensure nothing is broken
420+ let test_cases = [
421+ NodeType :: Assignment ,
422+ NodeType :: BinaryOperation ,
423+ NodeType :: FunctionCall ,
424+ NodeType :: ContractDefinition ,
425+ NodeType :: YulAssignment ,
426+ NodeType :: Other ( "CustomNodeType" . to_string ( ) ) ,
427+ ] ;
428+
429+ for original in test_cases {
430+ let serialized = serde_json:: to_string ( & original) . unwrap ( ) ;
431+ let deserialized: NodeType = serde_json:: from_str ( & serialized) . unwrap ( ) ;
432+ assert_eq ! ( original, deserialized) ;
433+ }
434+ }
435+
436+ #[ test]
437+ fn test_ast_node_with_unknown_type ( ) {
438+ // Test that a complete Node with unknown nodeType can be parsed
439+ let json = r#"{
440+ "id": 1,
441+ "nodeType": "NewFancyNodeType",
442+ "src": "0:0:0"
443+ }"# ;
444+
445+ let node: Node = serde_json:: from_str ( json) . unwrap ( ) ;
446+ assert_eq ! ( node. node_type, NodeType :: Other ( "NewFancyNodeType" . to_string( ) ) ) ;
447+ assert_eq ! ( node. id, Some ( 1 ) ) ;
448+ }
449+
450+ #[ test]
451+ fn test_mixed_known_unknown_nodes ( ) {
452+ // Test parsing a JSON structure with both known and unknown node types
453+ let json = r#"{
454+ "absolutePath": "/test/path.sol",
455+ "id": 0,
456+ "nodeType": "SourceUnit",
457+ "src": "0:100:0",
458+ "nodes": [
459+ {
460+ "id": 1,
461+ "nodeType": "Assignment",
462+ "src": "10:20:0"
463+ },
464+ {
465+ "id": 2,
466+ "nodeType": "FutureNodeType",
467+ "src": "30:40:0"
468+ }
469+ ]
470+ }"# ;
471+
472+ let ast: Ast = serde_json:: from_str ( json) . unwrap ( ) ;
473+ assert_eq ! ( ast. node_type, NodeType :: SourceUnit ) ;
474+ assert_eq ! ( ast. nodes. len( ) , 2 ) ;
475+ assert_eq ! ( ast. nodes[ 0 ] . node_type, NodeType :: Assignment ) ;
476+ assert_eq ! ( ast. nodes[ 1 ] . node_type, NodeType :: Other ( "FutureNodeType" . to_string( ) ) ) ;
477+ }
222478}
0 commit comments