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