Skip to content

Commit cb1d203

Browse files
committed
diagnostics: make experimental-html sink prettier [PR116792]
This patch to the "experimental-html" diagnostic sink: * adds use of the PatternFly 3 CSS library (via an optional link in the generated html to a copy in a CDN) * uses PatternFly's "alert" pattern to show severities for diagnostics, properly nesting "note" diagnostics for diagnostic groups. Example: before: https://dmalcolm.fedorapeople.org/gcc/2025-06-10/before/diagnostic-ranges.c.html after: https://dmalcolm.fedorapeople.org/gcc/2025-06-10/after/diagnostic-ranges.c.html * adds initial support for logical locations and physical locations * adds initial support for multi-level nested diagnostics such as those for C++ concepts diagnostics. Ideally this would show a clickable disclosure widget to expand/collapse a level, but for now it uses nested <ul> elements with <li> for the child diagnostics. Example: before: https://dmalcolm.fedorapeople.org/gcc/2025-06-10/before/nested-diagnostics-1.C.html after: https://dmalcolm.fedorapeople.org/gcc/2025-06-10/after/nested-diagnostics-1.C.html gcc/ChangeLog: PR other/116792 * diagnostic-format-html.cc: Include "diagnostic-path.h" and "diagnostic-client-data-hooks.h". (html_builder::m_logical_loc_mgr): New field. (html_builder::m_cur_nesting_levels): New field. (html_builder::m_last_logical_location): New field. (html_builder::m_last_location): New field. (html_builder::m_last_expanded_location): New field. (HTML_STYLE): Add "white-space: pre;" to .source and .annotation. Add "gcc-quoted-text" CSS class. (html_builder::html_builder): Initialize the new fields. If CSS is enabled, add CDN links to PatternFly 3 stylesheets. (html_builder::add_stylesheet): New. (html_builder::on_report_diagnostic): Add "alert" param to make_element_for_diagnostic, setting it by default, but unsetting it for nested diagnostics below the top level. Use add_at_nesting_level for nested diagnostics. (add_nesting_level_attr): New. (html_builder::add_at_nesting_level): New. (get_pf_class_for_alert_div): New. (get_pf_class_for_alert_icon): New. (get_label_for_logical_location_kind): New. (add_labelled_value): New. (html_builder::make_element_for_diagnostic): Add leading comment. Add "alert" param. Drop class="gcc-diagnostic" from <div> tag, instead adding the class for a PatternFly 3 alert if "alert" is true, and adding a <span> with an alert icon, both according to the diagnostic severity. Add a severity prefix to the message for alerts. Add any metadata/option text as suffixes to the message. Show any logical location. Show any physical location. Don't show the locus if the last location is unchanged within the diagnostic_group. Wrap any execution path element in a <div id="execution-path"> and add a label to it. Wrap any generated patch in a <div id="suggested-fix"> and add a label to it. (selftest::test_simple_log): Update expected HTML. gcc/testsuite/ChangeLog: PR other/116792 * gcc.dg/html-output/missing-semicolon.py: Update for changes to diagnostic elements. * gcc.dg/format/diagnostic-ranges-html.py: Likewise. * gcc.dg/plugin/diagnostic-test-metadata-html.py: Likewise. Drop out-of-date comment. * gcc.dg/plugin/diagnostic-test-paths-2.py: Likewise. * gcc.dg/plugin/diagnostic-test-paths-4.py: Likewise. Drop out-of-date comment. * gcc.dg/plugin/diagnostic-test-show-locus.py: Likewise. * lib/htmltest.py (get_diag_by_index): Update to use search by id. (get_message_within_diag): Update to use search by class. libcpp/ChangeLog: PR other/116792 * include/line-map.h (typedef expanded_location): Convert to... (struct expanded_location): ...this. (operator==): New decl, for expanded_location. (operator!=): Likewise. * line-map.cc (operator==): New decl, for expanded_location. Signed-off-by: David Malcolm <[email protected]>
1 parent 896edb1 commit cb1d203

File tree

10 files changed

+549
-227
lines changed

10 files changed

+549
-227
lines changed

gcc/diagnostic-format-html.cc

Lines changed: 405 additions & 28 deletions
Large diffs are not rendered by default.

gcc/testsuite/gcc.dg/format/diagnostic-ranges-html.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,20 @@ def test_message(html_tree):
1919
diag = get_diag_by_index(html_tree, 0)
2020
msg = get_message_within_diag(diag)
2121

22-
assert_tag(msg[0], 'span')
23-
assert_class(msg[0], 'gcc-quoted-text')
24-
assert_highlighted_text(msg[0][0], 'highlight-a', '%i')
25-
22+
assert_tag(msg[0], 'strong')
23+
assert msg[0].text == 'warning: '
24+
2625
assert_tag(msg[1], 'span')
2726
assert_class(msg[1], 'gcc-quoted-text')
28-
assert_highlighted_text(msg[1][0], 'highlight-a', 'int')
27+
assert_highlighted_text(msg[1][0], 'highlight-a', '%i')
2928

3029
assert_tag(msg[2], 'span')
3130
assert_class(msg[2], 'gcc-quoted-text')
32-
assert_highlighted_text(msg[2][0], 'highlight-b', 'const char *')
31+
assert_highlighted_text(msg[2][0], 'highlight-a', 'int')
32+
33+
assert_tag(msg[3], 'span')
34+
assert_class(msg[3], 'gcc-quoted-text')
35+
assert_highlighted_text(msg[3][0], 'highlight-b', 'const char *')
3336

3437
def test_annotations(html_tree):
3538
"""

gcc/testsuite/gcc.dg/html-output/missing-semicolon.py

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,22 +37,68 @@ def test_basics(html_tree):
3737

3838
diag = diag_list.find('xhtml:div', ns)
3939
assert diag is not None
40-
assert diag.attrib['class'] == 'gcc-diagnostic'
40+
assert diag.attrib['class'] == 'alert alert-danger'
41+
assert diag.attrib['id'] == 'gcc-diag-0'
4142

42-
message = diag.find('xhtml:span', ns)
43+
icon = diag.find('xhtml:span', ns)
44+
assert icon.attrib['class'] == 'pficon pficon-error-circle-o'
45+
46+
# The message line:
47+
message = diag.find("./xhtml:div[@class='gcc-message']", ns)
4348
assert message is not None
44-
assert message.attrib['class'] == 'gcc-message'
45-
assert message.text == "expected '"
46-
assert message[0].tag == make_tag('span')
47-
assert message[0].attrib['class'] == 'gcc-quoted-text'
48-
assert message[0].text == ';'
49-
assert message[0].tail == "' before '"
49+
# <html:div xmlns:html="http://www.w3.org/1999/xhtml" class="gcc-message" id="gcc-diag-0-message"><html:strong>error: </html:strong> expected '<html:span class="gcc-quoted-text">;</html:span>' before '<html:span class="gcc-quoted-text">}</html:span>' token</html:div>
50+
assert message[0].tag == make_tag('strong')
51+
assert message[0].text == 'error: '
52+
assert message[0].tail == " expected '"
5053
assert message[1].tag == make_tag('span')
5154
assert message[1].attrib['class'] == 'gcc-quoted-text'
52-
assert message[1].text == '}'
53-
assert message[1].tail == "' token"
55+
assert message[1].text == ';'
56+
assert message[1].tail == "' before '"
57+
assert message[2].tag == make_tag('span')
58+
assert message[2].attrib['class'] == 'gcc-quoted-text'
59+
assert message[2].text == '}'
60+
assert message[2].tail == "' token"
61+
62+
# Logical location
63+
logical_loc = diag.find("./xhtml:div[@id='logical-location']", ns)
64+
assert logical_loc is not None
65+
assert len(logical_loc) == 2
66+
assert logical_loc[0].tag == make_tag('span')
67+
assert logical_loc[0].text == 'Function '
68+
assert logical_loc[1].tag == make_tag('span')
69+
assert logical_loc[1].text == 'missing_semicolon'
70+
assert logical_loc[1].attrib['class'] == 'gcc-quoted-text'
71+
72+
# Physical location
73+
file_ = diag.find("./xhtml:div[@id='file']", ns)
74+
assert file_ is not None
75+
assert len(file_) == 2
76+
assert file_[0].tag == make_tag('span')
77+
assert file_[0].text == 'File '
78+
assert file_[1].tag == make_tag('span')
79+
assert file_[1].text.endswith('gcc/testsuite/gcc.dg/html-output/missing-semicolon.c')
80+
81+
line = diag.find("./xhtml:div[@id='line']", ns)
82+
assert line is not None
83+
assert len(line) == 2
84+
assert line[0].tag == make_tag('span')
85+
assert line[0].text == 'Line '
86+
assert line[1].tag == make_tag('span')
87+
assert line[1].text == '8'
88+
89+
column = diag.find("./xhtml:div[@id='column']", ns)
90+
assert column is not None
91+
assert len(column) == 2
92+
assert column[0].tag == make_tag('span')
93+
assert column[0].text == 'Column '
94+
assert column[1].tag == make_tag('span')
95+
assert column[1].text == '12'
5496

55-
pre = diag.find('xhtml:pre', ns)
97+
# Suggested fix
98+
fix = diag.find("./xhtml:div[@id='suggested-fix']", ns)
99+
label = fix.find('xhtml:label', ns)
100+
assert label.text == "Suggested fix"
101+
pre = fix.find('xhtml:pre', ns)
56102
assert pre is not None
57103
assert pre.attrib['class'] == 'gcc-generated-patch'
58104
assert pre.text.startswith('--- ')

gcc/testsuite/gcc.dg/plugin/diagnostic-test-metadata-html.py

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,24 @@ def test_metadata(html_tree):
2121

2222
diag = diag_list.find('xhtml:div', ns)
2323
assert diag is not None
24-
assert diag.attrib['class'] == 'gcc-diagnostic'
24+
assert diag.attrib['class'] == 'alert alert-warning'
2525

26-
spans = diag.findall('xhtml:span', ns)
27-
metadata = spans[1]
26+
icon = diag.find('xhtml:span', ns)
27+
assert icon.attrib['class'] == 'pficon pficon-warning-triangle-o'
28+
29+
message = diag.find("./xhtml:div[@class='gcc-message']", ns)
30+
assert message.attrib['id'] == 'gcc-diag-0-message'
31+
32+
assert message[0].tag == make_tag('strong')
33+
assert message[0].text == 'warning: '
34+
assert message[0].tail == " never use '"
35+
36+
assert message[1].tag == make_tag('span')
37+
assert message[1].attrib['class'] == 'gcc-quoted-text'
38+
assert message[1].text == 'gets'
39+
assert message[1].tail == "' "
40+
41+
metadata = message[2]
2842
assert metadata.attrib['class'] == 'gcc-metadata'
2943
assert metadata[0].tag == make_tag('span')
3044
assert metadata[0].attrib['class'] == 'gcc-metadata-item'
@@ -57,21 +71,3 @@ def test_metadata(html_tree):
5771
annotation_tr = rows[1]
5872
assert_annotation_line(annotation_tr,
5973
' ^~~~~~~~~~')
60-
61-
# For reference, here's the generated HTML:
62-
"""
63-
<body>
64-
<div class="gcc-diagnostic-list">
65-
<div class="gcc-diagnostic">
66-
<span class="gcc-message">never use &apos;<span class="gcc-quoted-text">gets</span>&apos;</span>
67-
<span class="gcc-metadata"><span class="gcc-metadata-item">[<a href="https://cwe.mitre.org/data/definitions/242.html">CWE-242</a>]</span><span class="gcc-metadata-item">[<a href="https://example.com/">STR34-C</a>]</span></span><table class="locus">
68-
<tbody class="line-span">
69-
<tr><td class="linenum"> 10</td> <td class="source"> gets (buf);</td></tr>
70-
<tr><td class="linenum"/><td class="annotation"> ^~~~~~~~~~</td></tr>
71-
</tbody>
72-
</table>
73-
74-
</div>
75-
</div>
76-
</body>
77-
"""

gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,16 @@ def test_paths(html_tree):
2121

2222
diag = diag_list.find('xhtml:div', ns)
2323
assert diag is not None
24-
assert diag.attrib['class'] == 'gcc-diagnostic'
24+
assert diag.attrib['class'] == 'alert alert-danger'
25+
assert diag.attrib['id'] == 'gcc-diag-0'
2526

26-
event_ranges = diag.find('xhtml:div', ns)
27+
exec_path = diag.find("./xhtml:div[@id='execution-path']", ns)
28+
assert exec_path is not None
29+
30+
label = exec_path.find('xhtml:label', ns)
31+
assert label.text == 'Execution path with 3 events'
32+
33+
event_ranges = exec_path.find('xhtml:div', ns)
2734
assert_class(event_ranges, 'event-ranges')
2835

2936
frame_margin = event_ranges.find('xhtml:table', ns)

gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-4.py

Lines changed: 7 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@ def test_paths(html_tree):
2525
assert_annotation_line(annotation_tr,
2626
' ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
2727

28-
event_ranges = diag.find('xhtml:div', ns)
28+
exec_path = diag.find("./xhtml:div[@id='execution-path']", ns)
29+
assert exec_path is not None
30+
31+
label = exec_path.find('xhtml:label', ns)
32+
assert label.text == 'Execution path with 9 events'
33+
34+
event_ranges = exec_path.find('xhtml:div', ns)
2935
assert_class(event_ranges, 'event-ranges')
3036

3137
test_frame_margin = event_ranges.find('xhtml:table', ns)
@@ -41,150 +47,3 @@ def test_paths(html_tree):
4147
test_frame = tds[1]
4248
assert_frame(test_frame, 'test')
4349
assert_event_range_with_margin(test_frame[1])
44-
45-
# For reference, generated HTML looks like this:
46-
"""
47-
<table class="stack-frame-with-margin"><tr>
48-
<td class="interprocmargin" style="padding-left: 100px"/>
49-
<td class="stack-frame">
50-
<div class="frame-funcname"><span>test</span></div><table class="event-range-with-margin"><tr>
51-
<td class="event-range">
52-
<div class="events-hdr"><span class="funcname">test</span>: <span class="event-ids">events 1-2</span></div>
53-
<table class="locus">
54-
<tbody class="line-span">
55-
<tr><td class="linenum"> 27</td> <td class="source">{</td></tr>
56-
<tr><td class="linenum"/><td class="annotation">^</td></tr>
57-
<tr><td class="linenum"/><td class="annotation">|</td></tr>
58-
<tr><td class="linenum"/><td class="annotation">(1) entering 'test'</td></tr>
59-
<tr><td class="linenum"> 28</td> <td class="source"> register_handler ();</td></tr>
60-
<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~</td></tr>
61-
<tr><td class="linenum"/><td class="annotation"> |</td></tr>
62-
<tr><td class="linenum"/><td class="annotation"> (2) calling 'register_handler'</td></tr>
63-
</tbody>
64-
</table>
65-
</td></tr></table>
66-
<div class="between-ranges-call">
67-
<svg height="30" width="150">
68-
<defs>
69-
<marker id="arrowhead" markerWidth="10" markerHeight="7"
70-
refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
71-
<polygon points="0 0, 10 3.5, 0 7"/>
72-
</marker>
73-
</defs>
74-
<polyline points="20,0 20,10 120,10 120,20"
75-
style="fill:none;stroke: #0088ce"
76-
marker-end="url(#arrowhead)"/>
77-
</svg>
78-
</div>
79-
80-
<table class="stack-frame-with-margin"><tr>
81-
<td class="interprocmargin" style="padding-left: 100px"/>
82-
<td class="stack-frame">
83-
<div class="frame-funcname"><span>register_handler</span></div><table class="event-range-with-margin"><tr>
84-
<td class="event-range">
85-
<div class="events-hdr"><span class="funcname">register_handler</span>: <span class="event-ids">events 3-4</span></div>
86-
<table class="locus">
87-
<tbody class="line-span">
88-
<tr><td class="linenum"> 22</td> <td class="source">{</td></tr>
89-
<tr><td class="linenum"/><td class="annotation">^</td></tr>
90-
<tr><td class="linenum"/><td class="annotation">|</td></tr>
91-
<tr><td class="linenum"/><td class="annotation">(3) entering 'register_handler'</td></tr>
92-
<tr><td class="linenum"> 23</td> <td class="source"> signal(SIGINT, int_handler);</td></tr>
93-
<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~</td></tr>
94-
<tr><td class="linenum"/><td class="annotation"> |</td></tr>
95-
<tr><td class="linenum"/><td class="annotation"> (4) registering 'int_handler' as signal handler</td></tr>
96-
</tbody>
97-
</table>
98-
</td></tr></table>
99-
</td></tr></table>
100-
</td></tr></table>
101-
<div class="between-ranges-return">
102-
<svg height="30" width="250">
103-
<defs>
104-
<marker id="arrowhead" markerWidth="10" markerHeight="7"
105-
refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
106-
<polygon points="0 0, 10 3.5, 0 7"/>
107-
</marker>
108-
</defs>
109-
<polyline points="220,0 220,10 20,10 20,20"
110-
style="fill:none;stroke: #0088ce"
111-
marker-end="url(#arrowhead)"/>
112-
</svg>
113-
</div>
114-
115-
<table class="event-range-with-margin"><tr>
116-
<td class="event-range">
117-
<div class="events-hdr"><span class="event-ids">event 5</span></div>
118-
(5): later on, when the signal is delivered to the process
119-
</td></tr></table>
120-
<div class="between-ranges-call">
121-
<svg height="30" width="150">
122-
<defs>
123-
<marker id="arrowhead" markerWidth="10" markerHeight="7"
124-
refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
125-
<polygon points="0 0, 10 3.5, 0 7"/>
126-
</marker>
127-
</defs>
128-
<polyline points="20,0 20,10 120,10 120,20"
129-
style="fill:none;stroke: #0088ce"
130-
marker-end="url(#arrowhead)"/>
131-
</svg>
132-
</div>
133-
134-
<table class="stack-frame-with-margin"><tr>
135-
<td class="interprocmargin" style="padding-left: 100px"/>
136-
<td class="stack-frame">
137-
<div class="frame-funcname"><span>int_handler</span></div><table class="event-range-with-margin"><tr>
138-
<td class="event-range">
139-
<div class="events-hdr"><span class="funcname">int_handler</span>: <span class="event-ids">events 6-7</span></div>
140-
<table class="locus">
141-
<tbody class="line-span">
142-
<tr><td class="linenum"> 17</td> <td class="source">{</td></tr>
143-
<tr><td class="linenum"/><td class="annotation">^</td></tr>
144-
<tr><td class="linenum"/><td class="annotation">|</td></tr>
145-
<tr><td class="linenum"/><td class="annotation">(6) entering 'int_handler'</td></tr>
146-
<tr><td class="linenum"> 18</td> <td class="source"> custom_logger("got signal");</td></tr>
147-
<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~</td></tr>
148-
<tr><td class="linenum"/><td class="annotation"> |</td></tr>
149-
<tr><td class="linenum"/><td class="annotation"> (7) calling 'custom_logger'</td></tr>
150-
</tbody>
151-
</table>
152-
</td></tr></table>
153-
<div class="between-ranges-call">
154-
<svg height="30" width="150">
155-
<defs>
156-
<marker id="arrowhead" markerWidth="10" markerHeight="7"
157-
refX="0" refY="3.5" orient="auto" stroke="#0088ce" fill="#0088ce">
158-
<polygon points="0 0, 10 3.5, 0 7"/>
159-
</marker>
160-
</defs>
161-
<polyline points="20,0 20,10 120,10 120,20"
162-
style="fill:none;stroke: #0088ce"
163-
marker-end="url(#arrowhead)"/>
164-
</svg>
165-
</div>
166-
167-
<table class="stack-frame-with-margin"><tr>
168-
<td class="interprocmargin" style="padding-left: 100px"/>
169-
<td class="stack-frame">
170-
<div class="frame-funcname"><span>custom_logger</span></div><table class="event-range-with-margin"><tr>
171-
<td class="event-range">
172-
<div class="events-hdr"><span class="funcname">custom_logger</span>: <span class="event-ids">events 8-9</span></div>
173-
<table class="locus">
174-
<tbody class="line-span">
175-
<tr><td class="linenum"> 12</td> <td class="source">{</td></tr>
176-
<tr><td class="linenum"/><td class="annotation">^</td></tr>
177-
<tr><td class="linenum"/><td class="annotation">|</td></tr>
178-
<tr><td class="linenum"/><td class="annotation">(8) entering 'custom_logger'</td></tr>
179-
<tr><td class="linenum"> 13</td> <td class="source"> fprintf(stderr, "LOG: %s", msg); /* { dg-warning "call to 'fprintf' from within signal handler" } */</td></tr>
180-
<tr><td class="linenum"/><td class="annotation"> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~</td></tr>
181-
<tr><td class="linenum"/><td class="annotation"> |</td></tr>
182-
<tr><td class="linenum"/><td class="annotation"> (9) calling 'fprintf'</td></tr>
183-
</tbody>
184-
</table>
185-
</td></tr></table>
186-
</td></tr></table>
187-
</td></tr></table>
188-
189-
</div>
190-
"""

gcc/testsuite/gcc.dg/plugin/diagnostic-test-show-locus.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def test_very_wide_line(html_tree):
4646
def test_fixit_insert(html_tree):
4747
diag = get_diag_by_index(html_tree, 3)
4848
msg = get_message_within_diag(diag)
49-
assert msg.text == 'example of insertion hints'
49+
assert msg[0].text == 'warning: '
50+
assert msg[0].tail == ' example of insertion hints'
5051

5152
src = get_locus_within_diag(diag)
5253

@@ -62,7 +63,8 @@ def test_fixit_insert(html_tree):
6263
def test_fixit_remove(html_tree):
6364
diag = get_diag_by_index(html_tree, 4)
6465
msg = get_message_within_diag(diag)
65-
assert msg.text == 'example of a removal hint'
66+
assert msg[0].text == 'warning: '
67+
assert msg[0].tail == ' example of a removal hint'
6668

6769
src = get_locus_within_diag(diag)
6870

@@ -78,7 +80,8 @@ def test_fixit_remove(html_tree):
7880
def test_fixit_replace(html_tree):
7981
diag = get_diag_by_index(html_tree, 5)
8082
msg = get_message_within_diag(diag)
81-
assert msg.text == 'example of a replacement hint'
83+
assert msg[0].text == 'warning: '
84+
assert msg[0].tail == ' example of a replacement hint'
8285

8386
src = get_locus_within_diag(diag)
8487

@@ -94,7 +97,8 @@ def test_fixit_replace(html_tree):
9497
def test_fixit_insert_newline(html_tree):
9598
diag = get_diag_by_index(html_tree, 6)
9699
msg = get_message_within_diag(diag)
97-
assert msg.text == 'example of newline insertion hint'
100+
assert msg[0].text == 'warning: '
101+
assert msg[0].tail == ' example of newline insertion hint'
98102

99103
src = get_locus_within_diag(diag)
100104

gcc/testsuite/lib/htmltest.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,11 @@ def get_diag_by_index(html_tree, index):
8383
assert diag_list is not None
8484
assert_class(diag_list, 'gcc-diagnostic-list')
8585

86-
diags = diag_list.findall('xhtml:div', ns)
87-
diag = diags[index]
88-
assert_class(diag, 'gcc-diagnostic')
86+
diag = diag_list.find(f"xhtml:div[@id='gcc-diag-{index}']", ns)
8987
return diag
9088

9189
def get_message_within_diag(diag_element):
92-
msg = diag_element.find('xhtml:span', ns)
93-
assert_class(msg, 'gcc-message')
90+
msg = diag_element.find("xhtml:div[@class='gcc-message']", ns)
9491
return msg
9592

9693
def get_locus_within_diag(diag_element):

0 commit comments

Comments
 (0)