Skip to content

Commit f0e3a5c

Browse files
committed
Next/Prev message cycles through test errors.
1 parent 324c259 commit f0e3a5c

File tree

5 files changed

+116
-22
lines changed

5 files changed

+116
-22
lines changed

cargo_build.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,8 @@ def run(self):
196196
return
197197
messages.clear_messages(self.window)
198198
p = rust_proc.RustProc()
199-
listener = opanel.OutputListener(self.window, self.working_dir)
199+
listener = opanel.OutputListener(self.window, self.working_dir,
200+
self.command_name)
200201
decode_json = util.get_setting('show_errors_inline', True) and \
201202
self.command_info.get('allows_json', False)
202203
try:

rust/messages.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,12 +111,15 @@ def add_message(window, path, span, level, is_main, text, markup_text, msg_cb):
111111
}
112112
messages = messages_by_path.setdefault(path, [])
113113

114-
phantom_text = PHANTOM_TEMPLATE.format(content=markup_text,
115-
error_color=util.get_setting('rust_syntax_error_color', 'var(--redish)'),
116-
warning_color=util.get_setting('rust_syntax_warning_color', 'var(--yellowish)'),
117-
note_color=util.get_setting('rust_syntax_note_color', 'var(--greenish)'),
118-
help_color=util.get_setting('rust_syntax_help_color', 'var(--bluish)'),
119-
)
114+
if markup_text:
115+
phantom_text = PHANTOM_TEMPLATE.format(content=markup_text,
116+
error_color=util.get_setting('rust_syntax_error_color', 'var(--redish)'),
117+
warning_color=util.get_setting('rust_syntax_warning_color', 'var(--yellowish)'),
118+
note_color=util.get_setting('rust_syntax_note_color', 'var(--greenish)'),
119+
help_color=util.get_setting('rust_syntax_help_color', 'var(--bluish)'),
120+
)
121+
else:
122+
phantom_text = None
120123
to_add = {
121124
'path': path,
122125
'level': level,
@@ -219,6 +222,8 @@ def check_in(region):
219222
def _show_phantom(view, level, span, message):
220223
if util.get_setting('rust_phantom_style', 'normal') == 'none':
221224
return
225+
if not message:
226+
return
222227
region = _span_to_region(view, span)
223228
# For some reason if you have a multi-line region, the phantom is only
224229
# displayed under the first line. I think it makes more sense for the

rust/opanel.py

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import sublime
44

55
import os
6+
import re
67
from . import rust_proc, messages, util
78

89
# Use the same panel name that Sublime's build system uses so that "Show Build
@@ -57,16 +58,42 @@ class OutputListener(rust_proc.ProcListener):
5758
# Sublime view used for output.
5859
output_view = None
5960

60-
def __init__(self, window, base_path):
61+
def __init__(self, window, base_path, command_name):
6162
self.window = window
6263
self.base_path = base_path
64+
self.command_name = command_name
6365

6466
def on_begin(self, proc):
6567
self.output_view = create_output_panel(self.window, self.base_path)
6668
self._append('[Running: %s]' % (' '.join(proc.cmd),))
6769

6870
def on_data(self, proc, data):
71+
region_start = self.output_view.size()
6972
self._append(data, nl=False)
73+
# Check for test errors.
74+
if self.command_name == 'test':
75+
# Re-fetch the data to handle things like \t expansion.
76+
appended = self.output_view.substr(
77+
sublime.Region(region_start, self.output_view.size()))
78+
m = re.search(r', ([^,<\n]*\.[A-z]{2}):([0-9]+):([0-9]+)',
79+
appended)
80+
if m:
81+
path = os.path.join(self.base_path, m.group(1))
82+
lineno = int(m.group(2)) - 1
83+
# Region columns appear to the left, so this is +1.
84+
col = int(m.group(3))
85+
span = ((lineno, col), (lineno, col))
86+
# +2 to skip ", "
87+
build_region = sublime.Region(region_start + m.start() + 2,
88+
region_start + m.end())
89+
90+
# Use callback so the build output window scrolls to this
91+
# point.
92+
def on_test_cb(message):
93+
message['output_panel_region'] = build_region
94+
95+
messages.add_message(self.window, path, span, 'error', True,
96+
None, None, on_test_cb)
7097

7198
def on_error(self, proc, message):
7299
self._append(message)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Tests for cycling through the errors from a test run.
2+
3+
#[test]
4+
fn passing() {
5+
}
6+
7+
#[test]
8+
fn basic_error1() {
9+
/*ERR 1 "tests/test_test_output.rs:9:46"*/assert!(false);
10+
}
11+
12+
#[test]
13+
fn basic_error2() {
14+
/*ERR 2 "tests/test_test_output.rs:14:47"*/assert_eq!(1, 0);
15+
}
16+
17+
#[test]
18+
fn basic_error3() {
19+
/*ERR 3 "tests/test_test_output.rs:19:47"*/assert_ne!(1, 1);
20+
}
21+
22+
#[test]
23+
fn custom_message() {
24+
/*ERR 4 "tests/test_test_output.rs:24:47"*/assert!(false, "Custom message");
25+
}
26+
27+
#[test]
28+
fn manual_panic() {
29+
/*ERR 5 "tests/test_test_output.rs:29:47"*/panic!("manual panic");
30+
}
31+
32+
#[test]
33+
#[should_panic(expected="xyz")]
34+
fn expected_panic1() {
35+
panic!("xyz");
36+
}
37+
38+
#[test]
39+
#[should_panic(expected="xyz")]
40+
fn expected_panic2() {
41+
}
42+
43+
#[test]
44+
#[ignore]
45+
fn ignored_test() {
46+
panic!("ignored");
47+
}
48+
49+
#[test]
50+
#[ignore]
51+
fn slow() {
52+
// This just prints a simple warning.
53+
std::thread::sleep(std::time::Duration::from_secs(65));
54+
}

tests/test_message_order.py

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ def setUp(self):
2222
window.run_command('cargo_set_target', {'target': 'auto',
2323
'variant': 'build',
2424
'package': pkg})
25+
window.run_command('cargo_set_target', {'target': 'auto',
26+
'variant': 'test',
27+
'package': pkg})
2528

2629
def test_message_order(self):
2730
"""Test message order.
@@ -32,35 +35,36 @@ def test_message_order(self):
3235
The files are annotated with comments to indicate where each message
3336
should appear and in which order. The annotations should look like:
3437
35-
/*ERR 1*/
36-
/*WARN 2*/
38+
/*ERR 1 "build_output_selection_inline" "build_output_selection_raw"*/
39+
/*WARN 1 "build_output_selection_inline" "build_output_selection_raw"*/
3740
3841
The number is the order the message should appear. Two numbers can be
39-
specified, where the second number is the "unsorted" sequence (the
40-
order the message is emitted from rustc).
42+
specified separated with a comma, where the second number is the
43+
"unsorted" sequence (the order the message is emitted from rustc).
4144
"""
4245
to_test = [
43-
('examples/ex_warning1.rs',
46+
('build', 'examples/ex_warning1.rs',
4447
'examples/warning1.rs', 'examples/warning2.rs'),
45-
('tests/test_all_levels.rs',),
48+
('build', 'tests/test_all_levels.rs',),
49+
('test', 'tests/test_test_output.rs',),
4650
]
47-
for paths in to_test:
51+
for command, *paths in to_test:
4852
rel_paths = [os.path.join('tests/message-order', path)
4953
for path in paths]
5054
sorted_msgs, unsorted_msgs = self._collect_message_order(rel_paths)
5155
self.assertTrue(sorted_msgs)
5256
self.assertTrue(unsorted_msgs)
5357
self._with_open_file(rel_paths[0], self._test_message_order,
54-
messages=sorted_msgs, inline=True)
58+
messages=sorted_msgs, inline=True, command=command)
5559
self._with_open_file(rel_paths[0],
5660
self._test_message_order, messages=unsorted_msgs,
57-
inline=False)
61+
inline=False, command=command)
5862

59-
def _test_message_order(self, view, messages, inline):
63+
def _test_message_order(self, view, messages, inline, command):
6064
self._override_setting('show_errors_inline', inline)
6165
self._cargo_clean(view)
6266
window = view.window()
63-
self._run_build_wait()
67+
self._run_build_wait(command)
6468

6569
def check_sequence(direction):
6670
omsgs = messages if direction == 'next' else reversed(messages)
@@ -105,7 +109,7 @@ def check_sequence(direction):
105109
# Test starting backwards.
106110
window.focus_view(view)
107111
self._cargo_clean(view)
108-
self._run_build_wait()
112+
self._run_build_wait(command)
109113
check_sequence('prev')
110114

111115
def _collect_message_order(self, paths):
@@ -133,7 +137,7 @@ def _collect_message_order(self, paths):
133137
[x[2:] for x in unsorted_result])
134138

135139
def _collect_message_order_view(self, view, result):
136-
pattern = r'/\*(ERR|WARN) ([0-9,]+) "([^"]+)" "([^"]+)"\*/'
140+
pattern = r'/\*(ERR|WARN) ([0-9,]+) "([^"]+)"(?: "([^"]+)")?\*/'
137141
regions = view.find_all(pattern)
138142

139143
def path_fixup(p):
@@ -152,7 +156,10 @@ def path_fixup(p):
152156
sort_index = int(m.group(2))
153157
unsorted = sort_index
154158
inline_highlight = path_fixup(m.group(3))
155-
raw_highlight = path_fixup(m.group(4))
159+
if m.group(4):
160+
raw_highlight = path_fixup(m.group(4))
161+
else:
162+
raw_highlight = inline_highlight
156163
result.append((sort_index, unsorted, view.file_name(),
157164
m.group(1), rowcol, inline_highlight, raw_highlight))
158165

0 commit comments

Comments
 (0)