11import json
2+ import sys
3+ import os
24import subprocess
35
46def print_code_snippet (file_path , line_num , context = 3 ):
@@ -31,52 +33,51 @@ def print_code_snippet(file_path, line_num, context=3):
3133 print (f"Could not read file { file_path } : { e } " )
3234
3335
34- def parse_rustc_json (stderr : str , file_path ):
35- """
36- Parses rustc's JSON output and prints only the first error with a single snippet.
37-
38- Args:
39- stderr (str): JSON-formatted stderr output from rustc.
40- file_path: Path to the Rust file.
36+ import json
4137
42- Returns:
43- None
38+ def parse_cargo_errors (output : str , output_rust ):
39+ """
40+ Parses Cargo’s JSON output and prints only the first compiler error it finds.
41+ Ignores warnings and notes entirely.
4442 """
45- for line in stderr .splitlines ():
43+ for line in output .splitlines ():
4644 line = line .strip ()
4745 if not line :
4846 continue
4947
5048 try :
51- diagnostic = json .loads (line )
49+ rec = json .loads (line )
5250 except json .JSONDecodeError :
5351 continue
5452
55- if diagnostic .get ("$message_type" ) != "diagnostic" :
53+ # Only look at compiler messages
54+ if rec .get ("reason" ) != "compiler-message" :
5655 continue
5756
58- if diagnostic .get ("level" ) != "error" :
57+ msg = rec ["message" ]
58+ # Skip anything that isn't an error
59+ if msg .get ("level" ) != "error" :
5960 continue
6061
61- message = diagnostic .get ("message" , "" )
62- spans = diagnostic .get ("spans" , [])
62+ text = msg .get ("message" , "" )
63+ spans = msg .get ("spans" , [])
6364
64- # Prefer the primary span in the current file
65+ # Print the high-level error first
66+ print (f"\n error: { text } " )
67+
68+ # Then try to show its primary location
6569 for span in spans :
66- if span .get ("is_primary" ) and span ["file_name" ] == file_path :
67- line_num = span ["line_start" ]
70+ if span .get ("is_primary" ):
71+ file = span .get ("file_name" )
72+ line_start = span .get ("line_start" )
6873 label = span .get ("label" , "" )
69- print (f"error: line { line_num } : { message } " )
70- if label :
71- print (f"--> { label } " )
72- print ("=" * 25 )
73- snippet = print_code_snippet (file_path , line_num , context = 8 )
74- print (snippet )
75- print ("=" * 25 )
76- return # we return because we only print the first error--in json format there can be multiple error messages(primary and non primary) for 1 error-- if you want to see them comment this line.
77-
78- # fallback: print the error message if no span in the current file
79- print (f"error: { message } " )
74+ print (f" --> { file } :{ line_start } { label } " .rstrip (), file = sys .stderr )
75+ # and a snippet
76+ snippet = print_code_snippet (output_rust + file , line_start , context = 5 )
77+ print ("\n " + snippet , file = sys .stderr )
78+ break
79+
80+ # Stop after the first error
8081 return
8182
8283def check_rust_test_errors (app , exception ):
@@ -86,31 +87,31 @@ def check_rust_test_errors(app, exception):
8687 This function is connected to the Sphinx build lifecycle and is executed after the build finishes.
8788 It invokes `rustc` in test mode on the generated Rust file and reports any compilation or test-related
8889 errors.
89-
90- Args:
91- app: The Sphinx application object. Must have an `output_rust_file` attribute containing
92- the path to the generated Rust source file.
93- exception: Exception raised during the build process, or None if the build completed successfully.
9490 """
95- rs_path = app .output_rust_file
91+ rs_path = app .output_rust
92+ cargo_toml_path = os .path .join (rs_path , "Cargo.toml" )
9693 # Run the Rust compiler in test mode with JSON error output format.
9794 # capturing stdout and stderr as text.
9895 result = subprocess .run (
99- ["rustc" , "--test" , "--edition=2024" , "--error-format=json" , "--emit=metadata" , rs_path ],
100- # --emit=metadata or else rustc will produce a binary ./generated
96+ [
97+ "cargo" ,
98+ "test" ,
99+ "--message-format=json" ,
100+ "--manifest-path" ,
101+ cargo_toml_path
102+ ],
101103 capture_output = True ,
102- text = True
104+ text = True ,
103105 )
104106
105107 if result .returncode != 0 :
106- print ("--- rustc Errors/Warnings ---" )
107- parse_rustc_json (result .stderr , app .output_rust_file )
108+ print ("\033 [31m --- Cargo test errors ---\033 [0m " )
109+ parse_cargo_errors (result .stdout , app .output_rust ) # parse stdout JSON lines
108110 # print("--- rustc Output ---")
109111 # print(result.stdout)
110-
111112 else :
112- print ("--- rustc Output ---" )
113- print (result .stdout )
114- if result .stderr :
115- print ("\n \n --- rustc Warnings---" )
116- print (result .stderr )
113+ print ("\033 [1;32mAll tests succeeded \033 [0m" ) # ANSI magic
114+ # print(result.stdout)
115+ # if result.stderr:
116+ # print("\n\n--- rustc Warnings ---")
117+ # print(result.stderr)
0 commit comments