#include "xml.h"
#include "xml-printer.h"
#include "json.h"
+#include "selftest-xml.h"
// struct html_generation_options
xp.pop_tag ("div");
}
+class html_token_printer : public token_printer
+{
+public:
+ html_token_printer (xml::element &parent_element)
+ /* Ideally pp_token_lists that reach a token_printer should be
+ "balanced", but for now they can have mismatching pp_tokens
+ e.g. a begin_color without an end_color (PR other/120610).
+ Give html_token_printer its own xml::printer as a firewall to
+ limit the scope of the mismatches in the HTML. */
+ : m_xp (parent_element,
+ /* Similarly we don't check that the popped tags match. */
+ false)
+ {
+ }
+ void print_tokens (pretty_printer */*pp*/,
+ const pp_token_list &tokens) final override
+ {
+ /* Implement print_tokens by adding child elements to
+ m_parent_element. */
+ for (auto iter = tokens.m_first; iter; iter = iter->m_next)
+ switch (iter->m_kind)
+ {
+ default:
+ gcc_unreachable ();
+
+ case pp_token::kind::text:
+ {
+ pp_token_text *sub = as_a <pp_token_text *> (iter);
+ /* The value might be in the obstack, so we may need to
+ copy it. */
+ m_xp.add_text (sub->m_value.get ());
+ }
+ break;
+
+ case pp_token::kind::begin_color:
+ {
+ pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter);
+ gcc_assert (sub->m_value.get ());
+ m_xp.push_tag_with_class ("span", sub->m_value.get ());
+ }
+ break;
+
+ case pp_token::kind::end_color:
+ m_xp.pop_tag ("span");
+ break;
+
+ case pp_token::kind::begin_quote:
+ {
+ m_xp.add_text (open_quote);
+ m_xp.push_tag_with_class ("span", "gcc-quoted-text");
+ }
+ break;
+ case pp_token::kind::end_quote:
+ {
+ m_xp.pop_tag ("span");
+ m_xp.add_text (close_quote);
+ }
+ break;
+
+ case pp_token::kind::begin_url:
+ {
+ pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
+ m_xp.push_tag ("a", true);
+ m_xp.set_attr ("href", sub->m_value.get ());
+ }
+ break;
+ case pp_token::kind::end_url:
+ m_xp.pop_tag ("a");
+ break;
+ }
+ }
+
+private:
+ xml::printer m_xp;
+};
+
/* Make a <div class="gcc-diagnostic"> for DIAGNOSTIC.
If ALERT is true, make it be a PatternFly alert (see
diagnostic_t orig_diag_kind,
bool alert)
{
- class html_token_printer : public token_printer
- {
- public:
- html_token_printer (xml::element &parent_element)
- /* Ideally pp_token_lists that reach a token_printer should be
- "balanced", but for now they can have mismatching pp_tokens
- e.g. a begin_color without an end_color (PR other/120610).
- Give html_token_printer its own xml::printer as a firewall to
- limit the scope of the mismatches in the HTML. */
- : m_xp (parent_element,
- /* Similarly we don't check that the popped tags match. */
- false)
- {
- }
- void print_tokens (pretty_printer */*pp*/,
- const pp_token_list &tokens) final override
- {
- /* Implement print_tokens by adding child elements to
- m_parent_element. */
- for (auto iter = tokens.m_first; iter; iter = iter->m_next)
- switch (iter->m_kind)
- {
- default:
- gcc_unreachable ();
-
- case pp_token::kind::text:
- {
- pp_token_text *sub = as_a <pp_token_text *> (iter);
- /* The value might be in the obstack, so we may need to
- copy it. */
- m_xp.add_text (sub->m_value.get ());
- }
- break;
-
- case pp_token::kind::begin_color:
- {
- pp_token_begin_color *sub = as_a <pp_token_begin_color *> (iter);
- gcc_assert (sub->m_value.get ());
- m_xp.push_tag_with_class ("span", sub->m_value.get ());
- }
- break;
-
- case pp_token::kind::end_color:
- m_xp.pop_tag ("span");
- break;
-
- case pp_token::kind::begin_quote:
- {
- m_xp.add_text (open_quote);
- m_xp.push_tag_with_class ("span", "gcc-quoted-text");
- }
- break;
- case pp_token::kind::end_quote:
- {
- m_xp.pop_tag ("span");
- m_xp.add_text (close_quote);
- }
- break;
-
- case pp_token::kind::begin_url:
- {
- pp_token_begin_url *sub = as_a <pp_token_begin_url *> (iter);
- m_xp.push_tag ("a", true);
- m_xp.set_attr ("href", sub->m_value.get ());
- }
- break;
- case pp_token::kind::end_url:
- m_xp.pop_tag ("a");
- break;
- }
- }
-
- private:
- xml::printer m_xp;
- };
-
const int diag_idx = m_next_diag_id++;
std::string diag_id;
{
namespace selftest {
+/* Helper for writing tests of html_token_printer.
+ Printing to m_pp will appear as HTML within m_top_element, a <div>. */
+
+struct token_printer_test
+{
+ token_printer_test ()
+ : m_top_element ("div", true),
+ m_tok_printer (m_top_element)
+ {
+ m_pp.set_token_printer (&m_tok_printer);
+ }
+
+ xml::element m_top_element;
+ html_token_printer m_tok_printer;
+ pretty_printer m_pp;
+};
+
+static void
+test_token_printer ()
+{
+ {
+ token_printer_test t;
+ pp_printf (&t.m_pp, "hello world");
+ ASSERT_XML_PRINT_EQ
+ (t.m_top_element,
+ "<div>hello world</div>\n");
+ }
+
+ {
+ token_printer_test t;
+ pp_printf (&t.m_pp, "%qs: %qs", "foo", "bar");
+ ASSERT_XML_PRINT_EQ
+ (t.m_top_element,
+ "<div>"
+ "`"
+ "<span class=\"gcc-quoted-text\">"
+ "foo"
+ "</span>"
+ "': `"
+ "<span class=\"gcc-quoted-text\">"
+ "bar"
+ "</span>"
+ "'"
+ "</div>\n");
+ }
+}
+
/* A subclass of html_output_format for writing selftests.
The XML output is cached internally, rather than written
out to a file. */
const xml::document &doc = dc.get_document ();
- pretty_printer pp;
- doc.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (doc,
("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<!DOCTYPE html\n"
" PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"\n"
diagnostic_metadata metadata;
metadata.add_cwe (415);
auto element = b.make_element_for_metadata (metadata);
- pretty_printer pp;
- element->write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (*element,
"<span class=\"gcc-metadata\">"
"<span class=\"gcc-metadata-item\">"
"["
"http://example.com");
metadata.add_rule (rule);
auto element = b.make_element_for_metadata (metadata);
- pretty_printer pp;
- element->write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (*element,
"<span class=\"gcc-metadata\">"
"<span class=\"gcc-metadata-item\">"
"["
diagnostic_format_html_cc_tests ()
{
auto_fix_quotes fix_quotes;
+ test_token_printer ();
test_simple_log ();
test_metadata ();
}
--- /dev/null
+/* Selftest support for XML.
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ Contributed by David Malcolm <dmalcolm@redhat.com>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_SELFTEST_XML_H
+#define GCC_SELFTEST_XML_H
+
+#include "xml.h"
+
+/* The selftest code should entirely disappear in a production
+ configuration, hence we guard all of it with #if CHECKING_P. */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Assert that NODE written with indentation as xml source
+ equals EXPECTED_VALUE.
+ Use LOC for any failures. */
+
+void
+assert_xml_print_eq (const location &loc,
+ const xml::node &node,
+ const char *expected_value);
+#define ASSERT_XML_PRINT_EQ(XML_NODE, EXPECTED_VALUE) \
+ assert_xml_print_eq ((SELFTEST_LOCATION), \
+ (XML_NODE), \
+ (EXPECTED_VALUE))
+
+} // namespace selftest
+
+#endif /* #if CHECKING_P */
+
+#endif /* GCC_SELFTEST_XML_H */
#include "xml-printer.h"
#include "pretty-print.h"
#include "selftest.h"
+#include "selftest-xml.h"
namespace xml {
namespace selftest {
+void
+assert_xml_print_eq (const location &loc,
+ const xml::node &node,
+ const char *expected_value)
+{
+ pretty_printer pp;
+ node.write_as_xml (&pp, 0, true);
+ ASSERT_STREQ_AT (loc, pp_formatted_text (&pp), expected_value);
+}
+
static void
test_no_dtd ()
{
xml::document doc;
- pretty_printer pp;
- doc.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (doc,
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
}
xp.pop_tag ("bar");
xp.pop_tag ("foo");
- pretty_printer pp;
- top.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (top,
"<top>\n"
" <foo>\n"
" hello\n"
xp.set_attr ("naseby", "1645");
xp.pop_tag ("alphabetical");
- pretty_printer pp;
- top.write_as_xml (&pp, 0, true);
- ASSERT_STREQ
- (pp_formatted_text (&pp),
+ ASSERT_XML_PRINT_EQ
+ (top,
"<top>\n"
" <chronological maldon=\"991\" hastings=\"1066\" edgehill=\"1642\" naseby=\"1645\"/>\n"
" <alphabetical edgehill=\"1642\" hastings=\"1066\" maldon=\"991\" naseby=\"1645\"/>\n"