11import json
22import os
3- from pathlib import Path
4- import shutil
53import sys
4+ from pathlib import Path
5+
6+ import eburger .settings as settings
7+ from eburger .serializer import parse_solidity_ast , reduce_json
68from eburger .utils .cli_args import args
9+ from eburger .utils .compilers import compile_foundry , compile_hardhat , compile_solc
710from eburger .utils .filesystem import (
811 create_directory_if_not_exists ,
9- create_or_empty_directory ,
10- find_and_read_sol_file ,
1112 find_recursive_files_by_patterns ,
12- get_foundry_ast_json ,
13- get_hardhat_ast_json ,
14- get_solidity_version_from_file ,
1513 roughly_check_valid_file_path_name ,
1614 select_project ,
1715)
1816from eburger .utils .helpers import (
19- construct_solc_cmdline ,
2017 get_eburger_version ,
21- get_filename_from_path ,
22- is_valid_json ,
23- run_command ,
2418)
2519from eburger .utils .installers import (
26- construct_sourceable_nvm_string ,
2720 install_foundry_if_not_found ,
2821 install_hardhat_if_not_found ,
29- set_solc_compiler_version ,
3022)
3123from eburger .utils .logger import log
32- import eburger .settings as settings
33- from eburger .serializer import parse_solidity_ast , reduce_json
3424from eburger .utils .outputs import (
3525 calculate_nsloc ,
3626 draw_nsloc_table ,
@@ -46,15 +36,28 @@ def main():
4636 print (get_eburger_version ())
4737 sys .exit (0 )
4838
49- if not args .solidity_file_or_folder and not args . ast_json_file :
39+ if not args .solidity_file_or_folder :
5040 args .solidity_file_or_folder = "."
5141
5242 log ("debug" , f"Project path: { args .solidity_file_or_folder } " )
5343
5444 create_directory_if_not_exists (settings .outputs_dir )
5545 path_type = None
5646
57- if args .solidity_file_or_folder :
47+ if args .ast_json_file :
48+ filename = args .ast_json_file
49+ filename = filename .replace (".json" , "" ) # Clean possible file extension
50+ filename = filename .replace (
51+ ".eburger/" , ""
52+ ) # Protection against analysis of files inside the output path
53+ with open (args .ast_json_file , "r" ) as f :
54+ ast_json = json .load (f )
55+ ast_json , src_paths = reduce_json (ast_json )
56+ output_path = settings .outputs_dir / f"{ filename } .json"
57+
58+ save_as_json (output_path , ast_json )
59+
60+ elif args .solidity_file_or_folder :
5861 if os .path .isfile (args .solidity_file_or_folder ):
5962 log ("debug" , f"Path type: file" )
6063 path_type = "file"
@@ -111,161 +114,40 @@ def main():
111114 )
112115 sys .exit (0 )
113116
114- elif args .ast_json_file :
115- filename = args .ast_json_file
116- filename = filename .replace (".json" , "" ) # Clean possible file extension
117- filename = filename .replace (
118- ".eburger/" , ""
119- ) # Protection against analysis of files inside the output path
120- with open (args .ast_json_file , "r" ) as f :
121- ast_json = json .load (f )
122- ast_json , src_paths = reduce_json (ast_json )
123- output_path = settings .outputs_dir / f"{ filename } .json"
124-
125- save_as_json (output_path , ast_json )
126-
127117 # NSLOC only mode
128118 if args .nsloc :
129119 draw_nsloc_table ()
130120
121+ # Compilation
131122 if path_type is not None :
132- # Foundry compilation flow
133123 if path_type == "foundry" :
134124 log ("info" , "Foundry project detected, compiling using forge." )
135125 _ , forge_full_path_binary_found = install_foundry_if_not_found ()
136126
137127 if args .solc_remappings :
138128 log ("warning" , "Ignoring the -r option in foundry based projects." )
139129
140- # Call foundry's full path if necessary, otherwise use the bins available through PATH
141- forge_clean_command = "forge clean"
142- if forge_full_path_binary_found :
143- forge_clean_command = (
144- f"{ os .environ .get ('HOME' )} /.foundry/bin/{ forge_clean_command } "
145- )
146-
147- run_command (forge_clean_command , directory = args .solidity_file_or_folder )
148- forge_out_dir = settings .outputs_dir / "forge-output"
149- create_or_empty_directory (forge_out_dir )
150-
151- foundry_excluded_dirs = " " .join (
152- [item for item in settings .excluded_dirs if item != "lib" ]
153- )
154- # Call foundry's full path if necessary, otherwise use the bins available through PATH
155- forge_build_command = f"forge build --force --skip { foundry_excluded_dirs } --build-info --build-info-path { forge_out_dir } "
156- if forge_full_path_binary_found :
157- forge_build_command = (
158- f"{ os .environ .get ('HOME' )} /.foundry/bin/{ forge_build_command } "
159- )
160-
161- run_command (
162- forge_build_command ,
163- directory = args .solidity_file_or_folder ,
164- live_output = args .debug ,
130+ output_filename , ast_json , filename , src_paths = compile_foundry (
131+ forge_full_path_binary_found
165132 )
166- sample_file_path = find_and_read_sol_file (args .solidity_file_or_folder )
167- filename , output_filename = get_filename_from_path (sample_file_path )
168- ast_json = get_foundry_ast_json (forge_out_dir )
169- ast_json , src_paths = reduce_json (ast_json )
170133 save_as_json (output_filename , ast_json )
171134
172- # Hardhat compilation flow
173135 elif path_type == "hardhat" :
174136 log ("info" , "Hardhat project detected, compiling using hardhat." )
175137 install_hardhat_if_not_found ()
176138
177139 if args .solc_remappings :
178140 log ("warning" , "Ignoring the -r option in hardhat based projects." )
179141
180- # try runing npx normally, as a fallback try the construct_sourceable_nvm_string method
181- # if a user hadn't got npx installed / or it's not on path (meaning it was installed in same run as the analysis)
182- # it still needs the fallback option
183- try :
184- run_command (f"npx hardhat clean" , directory = settings .project_root )
185- run_command (
186- f"npx hardhat compile --force" ,
187- directory = settings .project_root ,
188- live_output = args .debug ,
189- )
190- except FileNotFoundError :
191- run_command (
192- construct_sourceable_nvm_string ("npx hardhat clean" ),
193- directory = settings .project_root ,
194- )
195- run_command (
196- construct_sourceable_nvm_string ("npx hardhat compile --force" ),
197- directory = settings .project_root ,
198- live_output = args .debug ,
199- )
200-
201- # Copy compilation results to .eburger
202- expected_hardhat_outfiles = os .path .join (
203- args .solidity_file_or_folder , "artifacts" , "build-info"
204- )
205- if not os .path .isdir (expected_hardhat_outfiles ):
206- log (
207- "error" ,
208- f"Hardhat's compilation files were not found in expected location { expected_hardhat_outfiles } " ,
209- )
210- hardhat_out_dir = settings .outputs_dir / "hardhat-output"
211- if os .path .exists (hardhat_out_dir ):
212- shutil .rmtree (hardhat_out_dir )
213- shutil .copytree (expected_hardhat_outfiles , hardhat_out_dir )
214-
215- sample_file_path = find_and_read_sol_file (args .solidity_file_or_folder )
216- filename , output_filename = get_filename_from_path (sample_file_path )
217-
218- ast_json = get_hardhat_ast_json (hardhat_out_dir )
219- ast_json , src_paths = reduce_json (ast_json )
142+ output_filename , ast_json , filename , src_paths = compile_hardhat ()
220143 save_as_json (output_filename , ast_json )
221144
222145 # solc compilation flow
223146 elif path_type in ["file" , "folder" ]:
224- try :
225- run_command ("solc --version" )
226- run_command ("solc-select versions" )
227- except FileNotFoundError :
228- log (
229- "info" ,
230- "Please ensure solc and solc-select are installed and availble globally, and run again." ,
231- )
232- sys .exit (0 )
233-
234- sample_file_path = args .solidity_file_or_folder
235- compilation_source_path = args .solidity_file_or_folder
236-
237- if path_type == "folder" :
238- sample_file_path = find_and_read_sol_file (args .solidity_file_or_folder )
239-
240- filename , output_filename = get_filename_from_path (sample_file_path )
147+ output_filename , ast_json , filename , src_paths , solc_compile_res_parsed = (
148+ compile_solc (path_type )
149+ )
241150
242- if args .solc_compiler_version :
243- solc_required_version = args .solc_compiler_version
244- else :
245- solc_required_version = get_solidity_version_from_file (sample_file_path )
246- set_solc_compiler_version (solc_required_version )
247- solc_cmdline = construct_solc_cmdline (path_type , compilation_source_path )
248- if solc_cmdline is None :
249- log ("error" , "Error constructing solc command line" )
250-
251- solc_compile_res , _ = run_command (solc_cmdline , live_output = args .debug )
252-
253- # We continue as long as solc compiled something
254- if not is_valid_json (solc_compile_res ):
255- error_string = "Locally installed solc errored out trying to compile the contract. Please review comiler warnings above"
256- if not args .solc_remappings :
257- error_string += (
258- "or see if library remappings (using the -r option) are needed"
259- )
260- if not args .solc_compiler_version :
261- error_string += ", or try specifing the solidity compiler version (using the -s option)"
262- error_string += "."
263- log (
264- "error" ,
265- error_string ,
266- )
267- solc_compile_res_parsed = json .loads ("" .join (solc_compile_res ))
268- ast_json , src_paths = reduce_json (solc_compile_res_parsed )
269151 save_as_json (output_filename , solc_compile_res_parsed )
270152
271153 # Parse AST
0 commit comments