@@ -11,7 +11,11 @@ use foundry_test_utils::foundry_compilers::{
1111} ;
1212
1313use foundry_zksync_compilers:: {
14- artifacts:: { contract:: Contract , error:: Error } ,
14+ artifacts:: {
15+ contract:: Contract ,
16+ error:: Error ,
17+ output_selection:: { FileOutputSelection , OutputSelection , OutputSelectionFlag } ,
18+ } ,
1519 compilers:: {
1620 artifact_output:: zk:: ZkArtifactOutput ,
1721 zksolc:: {
@@ -24,7 +28,7 @@ use foundry_zksync_compilers::{
2428use semver:: Version ;
2529
2630#[ test]
27- fn zksync_can_compile_dapp_sample ( ) {
31+ fn test_zk_can_compile_dapp_sample ( ) {
2832 // let _ = tracing_subscriber::fmt()
2933 // .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
3034 // .try_init()
@@ -55,7 +59,7 @@ fn zksync_can_compile_dapp_sample() {
5559}
5660
5761#[ test]
58- fn zksync_can_compile_dapp_sample_with_supported_zksolc_versions ( ) {
62+ fn test_zk_can_compile_dapp_sample_with_supported_zksolc_versions ( ) {
5963 for version in ZkSolc :: zksolc_supported_versions ( ) {
6064 let root = PathBuf :: from ( env ! ( "CARGO_MANIFEST_DIR" ) ) . join ( "test-data/dapp-sample" ) ;
6165 let paths = ProjectPathsConfig :: builder ( ) . sources ( root. join ( "src" ) ) . lib ( root. join ( "lib" ) ) ;
@@ -82,7 +86,7 @@ fn zksync_can_compile_dapp_sample_with_supported_zksolc_versions() {
8286}
8387
8488#[ test]
85- fn zksync_can_set_hash_type_with_supported_versions ( ) {
89+ fn test_zk_can_set_hash_type_with_supported_versions ( ) {
8690 for version in ZkSolc :: zksolc_supported_versions ( ) {
8791 let mut project = TempProject :: < ZkSolcCompiler , ZkArtifactOutput > :: dapptools ( ) . unwrap ( ) ;
8892 project. project_mut ( ) . settings . set_zksolc_version ( version. clone ( ) ) . unwrap ( ) ;
@@ -167,14 +171,14 @@ fn test_zksync_can_compile_contract_with_suppressed_errors(zksolc_version: Versi
167171}
168172
169173#[ test]
170- fn zksync_can_compile_contract_with_suppressed_errors ( ) {
174+ fn test_zk_can_compile_contract_with_suppressed_errors ( ) {
171175 test_zksync_can_compile_contract_with_suppressed_errors (
172176 ZkSolc :: zksolc_latest_supported_version ( ) ,
173177 ) ;
174178}
175179
176180#[ test]
177- fn zksync_pre_1_5_7_can_compile_contract_with_suppressed_errors ( ) {
181+ fn test_zk_pre_1_5_7_can_compile_contract_with_suppressed_errors ( ) {
178182 test_zksync_can_compile_contract_with_suppressed_errors ( Version :: new ( 1 , 5 , 6 ) ) ;
179183}
180184
@@ -231,14 +235,14 @@ fn test_zksync_can_compile_contract_with_suppressed_warnings(zksolc_version: Ver
231235}
232236
233237#[ test]
234- fn zksync_can_compile_contract_with_suppressed_warnings ( ) {
238+ fn test_zk_can_compile_contract_with_suppressed_warnings ( ) {
235239 test_zksync_can_compile_contract_with_suppressed_warnings (
236240 ZkSolc :: zksolc_latest_supported_version ( ) ,
237241 ) ;
238242}
239243
240244#[ test]
241- fn zksync_pre_1_5_7_can_compile_contract_with_suppressed_warnings ( ) {
245+ fn test_zk_pre_1_5_7_can_compile_contract_with_suppressed_warnings ( ) {
242246 test_zksync_can_compile_contract_with_suppressed_warnings ( Version :: new ( 1 , 5 , 6 ) ) ;
243247}
244248
@@ -297,14 +301,14 @@ fn test_zksync_can_compile_contract_with_assembly_create_suppressed_warnings(
297301}
298302
299303#[ test]
300- fn zksync_can_compile_contract_with_assembly_create_suppressed_warnings_1_5_10 ( ) {
304+ fn test_zk_can_compile_contract_with_assembly_create_suppressed_warnings_1_5_10 ( ) {
301305 test_zksync_can_compile_contract_with_assembly_create_suppressed_warnings ( Version :: new (
302306 1 , 5 , 10 ,
303307 ) ) ;
304308}
305309
306310#[ test]
307- fn zksync_can_compile_dapp_detect_changes_in_libs ( ) {
311+ fn test_zk_can_compile_dapp_detect_changes_in_libs ( ) {
308312 // let _ = tracing_subscriber::fmt()
309313 // .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
310314 // .try_init()
@@ -381,7 +385,7 @@ fn zksync_can_compile_dapp_detect_changes_in_libs() {
381385}
382386
383387#[ test]
384- fn zksync_can_compile_dapp_detect_changes_in_sources ( ) {
388+ fn test_zk_can_compile_dapp_detect_changes_in_sources ( ) {
385389 let project = TempProject :: < ZkSolcCompiler , ZkArtifactOutput > :: dapptools ( ) . unwrap ( ) ;
386390
387391 let src = project
@@ -470,7 +474,7 @@ fn zksync_can_compile_dapp_detect_changes_in_sources() {
470474}
471475
472476#[ test]
473- fn zksync_can_emit_build_info ( ) {
477+ fn test_zk_can_emit_build_info ( ) {
474478 let mut project = TempProject :: < ZkSolcCompiler , ZkArtifactOutput > :: dapptools ( ) . unwrap ( ) ;
475479 project. project_mut ( ) . build_info = true ;
476480 project
@@ -512,7 +516,7 @@ contract B { }
512516}
513517
514518#[ test]
515- fn zksync_can_clean_build_info ( ) {
519+ fn test_zk_can_clean_build_info ( ) {
516520 let mut project = TempProject :: < ZkSolcCompiler , ZkArtifactOutput > :: dapptools ( ) . unwrap ( ) ;
517521
518522 project. project_mut ( ) . build_info = true ;
@@ -559,7 +563,7 @@ contract B { }
559563}
560564
561565#[ test]
562- fn zksync_cant_compile_a_file_outside_allowed_paths ( ) {
566+ fn test_zk_cant_compile_a_file_outside_allowed_paths ( ) {
563567 // For this test we should create the following directory structure:
564568 // project_root/
565569 // ├── outer/
@@ -636,7 +640,7 @@ contract Util {}
636640}
637641
638642#[ test]
639- fn zksync_can_compile_a_file_in_allowed_paths_successfully ( ) {
643+ fn test_zk_can_compile_a_file_in_allowed_paths_successfully ( ) {
640644 let tmp_dir = tempfile:: tempdir ( ) . unwrap ( ) ;
641645 let project_root = tmp_dir. path ( ) . to_path_buf ( ) ;
642646 let contracts_dir = tempfile:: tempdir_in ( & project_root) . unwrap ( ) ;
@@ -699,7 +703,7 @@ contract Util {}
699703}
700704
701705#[ test]
702- fn zksync_can_compile_yul_sample ( ) {
706+ fn test_zk_can_compile_yul_sample ( ) {
703707 // let _ = tracing_subscriber::fmt()
704708 // .with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
705709 // .try_init()
@@ -732,7 +736,7 @@ fn zksync_can_compile_yul_sample() {
732736}
733737
734738#[ test]
735- fn zksync_detects_change_on_cache_if_zksolc_version_changes ( ) {
739+ fn test_zk_detects_change_on_cache_if_zksolc_version_changes ( ) {
736740 let mut project = TempProject :: < ZkSolcCompiler , ZkArtifactOutput > :: dapptools ( ) . unwrap ( ) ;
737741
738742 project. project_mut ( ) . build_info = true ;
@@ -784,3 +788,181 @@ contract B { }
784788 assert_eq ! ( zksolc_version, "\" 1.5.7\" " ) ;
785789 }
786790}
791+
792+ #[ test]
793+ fn test_zk_can_compile_with_ast_output ( ) {
794+ let mut project = TempProject :: < ZkSolcCompiler , ZkArtifactOutput > :: dapptools ( ) . unwrap ( ) ;
795+
796+ // Configure output selection to include AST
797+ let mut settings = project. project ( ) . settings . clone ( ) ;
798+ settings. settings . output_selection = OutputSelection {
799+ all : FileOutputSelection {
800+ per_file : [ OutputSelectionFlag :: AST ] . into ( ) ,
801+ per_contract : [ OutputSelectionFlag :: ABI , OutputSelectionFlag :: Metadata ] . into ( ) ,
802+ } ,
803+ } ;
804+ project. project_mut ( ) . settings = settings;
805+
806+ project
807+ . add_source (
808+ "TestContract" ,
809+ r#"
810+ // SPDX-License-Identifier: MIT
811+ pragma solidity ^0.8.10;
812+
813+ contract TestContract {
814+ uint256 public value;
815+
816+ event ValueChanged(uint256 indexed newValue);
817+
818+ constructor(uint256 _initialValue) {
819+ value = _initialValue;
820+ }
821+
822+ function setValue(uint256 _newValue) public {
823+ value = _newValue;
824+ emit ValueChanged(_newValue);
825+ }
826+
827+ function getValue() public view returns (uint256) {
828+ return value;
829+ }
830+ }
831+ "# ,
832+ )
833+ . unwrap ( ) ;
834+
835+ let compiled = project. compile ( ) . unwrap ( ) ;
836+ compiled. assert_success ( ) ;
837+
838+ let sources = & compiled. output ( ) . sources ;
839+ let ( _path, versioned_files) = sources
840+ . 0
841+ . iter ( )
842+ . find ( |( path, _) | {
843+ path. file_name ( ) . and_then ( |name| name. to_str ( ) ) == Some ( "TestContract.sol" )
844+ } )
845+ . expect ( "TestContract.sol source not found" ) ;
846+
847+ let versioned_source_file = & versioned_files[ 0 ] ; // Get first version
848+ let source_file = & versioned_source_file. source_file ;
849+
850+ assert ! ( source_file. ast. is_some( ) , "AST should be present in source file" ) ;
851+ let ast =
852+ serde_json:: to_value ( source_file. ast . as_ref ( ) . unwrap ( ) ) . expect ( "Failed to serialize AST" ) ;
853+
854+ assert_eq ! ( ast[ "nodeType" ] . as_str( ) , Some ( "SourceUnit" ) , "AST root should be SourceUnit" ) ;
855+ assert ! ( ast[ "src" ] . is_string( ) , "AST should have src field" ) ;
856+ assert ! ( ast[ "nodes" ] . is_array( ) , "AST should have nodes array" ) ;
857+
858+ let nodes = ast[ "nodes" ] . as_array ( ) . expect ( "nodes should be array" ) ;
859+ assert ! ( !nodes. is_empty( ) , "AST nodes should not be empty" ) ;
860+
861+ // Find the contract definition node
862+ let contract_node = nodes
863+ . iter ( )
864+ . find ( |node| {
865+ node[ "nodeType" ] . as_str ( ) == Some ( "ContractDefinition" )
866+ && node[ "name" ] . as_str ( ) == Some ( "TestContract" )
867+ } )
868+ . expect ( "Should find TestContract definition in AST" ) ;
869+
870+ assert ! ( contract_node[ "src" ] . is_string( ) , "Contract node should have src field" ) ;
871+ assert ! ( contract_node[ "nodes" ] . is_array( ) , "Contract should have nodes array" ) ;
872+
873+ let contract_nodes = contract_node[ "nodes" ] . as_array ( ) . expect ( "Contract nodes should be array" ) ;
874+
875+ let has_constructor = contract_nodes. iter ( ) . any ( |node| {
876+ node[ "nodeType" ] . as_str ( ) == Some ( "FunctionDefinition" )
877+ && node[ "kind" ] . as_str ( ) == Some ( "constructor" )
878+ } ) ;
879+ assert ! ( has_constructor, "Should find constructor in AST" ) ;
880+
881+ let has_set_value_function = contract_nodes. iter ( ) . any ( |node| {
882+ node[ "nodeType" ] . as_str ( ) == Some ( "FunctionDefinition" )
883+ && node[ "name" ] . as_str ( ) == Some ( "setValue" )
884+ } ) ;
885+ assert ! ( has_set_value_function, "Should find setValue function in AST" ) ;
886+
887+ let has_value_variable = contract_nodes. iter ( ) . any ( |node| {
888+ node[ "nodeType" ] . as_str ( ) == Some ( "VariableDeclaration" )
889+ && node[ "name" ] . as_str ( ) == Some ( "value" )
890+ } ) ;
891+ assert ! ( has_value_variable, "Should find value variable in AST" ) ;
892+
893+ let has_event = contract_nodes. iter ( ) . any ( |node| {
894+ node[ "nodeType" ] . as_str ( ) == Some ( "EventDefinition" )
895+ && node[ "name" ] . as_str ( ) == Some ( "ValueChanged" )
896+ } ) ;
897+ assert ! ( has_event, "Should find ValueChanged event in AST" ) ;
898+ }
899+
900+ #[ test]
901+ fn test_zk_ast_available_in_sources ( ) {
902+ let mut project = TempProject :: < ZkSolcCompiler , ZkArtifactOutput > :: dapptools ( ) . unwrap ( ) ;
903+
904+ // Configure output selection to include AST
905+ let mut settings = project. project ( ) . settings . clone ( ) ;
906+ settings. settings . output_selection = OutputSelection {
907+ all : FileOutputSelection {
908+ per_file : [ OutputSelectionFlag :: AST ] . into ( ) ,
909+ per_contract : [ OutputSelectionFlag :: ABI ] . into ( ) ,
910+ } ,
911+ } ;
912+ project. project_mut ( ) . settings = settings;
913+
914+ project
915+ . add_source (
916+ "SimpleAstTest" ,
917+ r#"
918+ // SPDX-License-Identifier: MIT
919+ pragma solidity ^0.8.10;
920+
921+ contract SimpleAstTest {
922+ uint256 public counter;
923+
924+ function increment() public {
925+ counter += 1;
926+ }
927+ }
928+ "# ,
929+ )
930+ . unwrap ( ) ;
931+
932+ let compiled = project. compile ( ) . unwrap ( ) ;
933+ compiled. assert_success ( ) ;
934+
935+ let sources = & compiled. output ( ) . sources ;
936+ let ( _path, versioned_files) = sources
937+ . 0
938+ . iter ( )
939+ . find ( |( path, _) | {
940+ path. file_name ( ) . and_then ( |name| name. to_str ( ) ) == Some ( "SimpleAstTest.sol" )
941+ } )
942+ . expect ( "SimpleAstTest.sol source not found" ) ;
943+
944+ let versioned_source_file = & versioned_files[ 0 ] ; // Get first version
945+ let source_file = & versioned_source_file. source_file ;
946+
947+ assert ! ( source_file. ast. is_some( ) , "AST should be present in source file" ) ;
948+ let ast =
949+ serde_json:: to_value ( source_file. ast . as_ref ( ) . unwrap ( ) ) . expect ( "Failed to serialize AST" ) ;
950+
951+ assert_eq ! ( ast[ "nodeType" ] . as_str( ) , Some ( "SourceUnit" ) ) ;
952+
953+ let nodes = ast[ "nodes" ] . as_array ( ) . expect ( "AST should have nodes" ) ;
954+ let contract_node = nodes
955+ . iter ( )
956+ . find ( |node| {
957+ node[ "nodeType" ] . as_str ( ) == Some ( "ContractDefinition" )
958+ && node[ "name" ] . as_str ( ) == Some ( "SimpleAstTest" )
959+ } )
960+ . expect ( "Should find SimpleAstTest in AST" ) ;
961+
962+ let contract_elements = contract_node[ "nodes" ] . as_array ( ) . expect ( "Contract should have nodes" ) ;
963+ let has_counter_var = contract_elements. iter ( ) . any ( |node| {
964+ node[ "nodeType" ] . as_str ( ) == Some ( "VariableDeclaration" )
965+ && node[ "name" ] . as_str ( ) == Some ( "counter" )
966+ } ) ;
967+ assert ! ( has_counter_var, "Should find counter variable in AST" ) ;
968+ }
0 commit comments