Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(verifier): allow simplifying graph output data #5286

Merged
merged 1 commit into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions kythe/cxx/verifier/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ cc_library(
srcs = ["pretty_printer.cc"],
hdrs = ["pretty_printer.h"],
deps = [
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
],
)
52 changes: 24 additions & 28 deletions kythe/cxx/verifier/pretty_printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
#include <bitset>

#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"

namespace kythe {
namespace verifier {

PrettyPrinter::~PrettyPrinter() {}

void StringPrettyPrinter::Print(const std::string& string) { data_ << string; }

void StringPrettyPrinter::Print(absl::string_view string) { data_ << string; }
void StringPrettyPrinter::Print(const char* string) { data_ << string; }

void StringPrettyPrinter::Print(const void* ptr) {
Expand All @@ -37,7 +37,7 @@ void StringPrettyPrinter::Print(const void* ptr) {
}
}

void FileHandlePrettyPrinter::Print(const std::string& string) {
void FileHandlePrettyPrinter::Print(absl::string_view string) {
absl::FPrintF(file_, "%s", string);
}

Expand All @@ -49,50 +49,46 @@ void FileHandlePrettyPrinter::Print(const void* ptr) {
absl::FPrintF(file_, "0x%016llx", reinterpret_cast<unsigned long long>(ptr));
}

void QuoteEscapingPrettyPrinter::Print(const std::string& string) {
Print(string.c_str());
}

void QuoteEscapingPrettyPrinter::Print(const char* string) {
char buf[2];
buf[1] = 0;
while ((buf[0] = *string++)) {
if (buf[0] == '\"') {
void QuoteEscapingPrettyPrinter::Print(absl::string_view string) {
for (char ch : string) {
if (ch == '\"') {
wrapped_.Print("\\\"");
} else if (buf[0] == '\n') {
} else if (ch == '\n') {
wrapped_.Print("\\n");
} else if (buf[0] == '\'') {
} else if (ch == '\'') {
wrapped_.Print("\\\'");
} else {
wrapped_.Print(buf);
wrapped_.Print({&ch, 1});
}
}
}

void QuoteEscapingPrettyPrinter::Print(const void* ptr) { wrapped_.Print(ptr); }

void HtmlEscapingPrettyPrinter::Print(const std::string& string) {
Print(string.c_str());
void QuoteEscapingPrettyPrinter::Print(const char* string) {
Print(absl::string_view(string));
}

void HtmlEscapingPrettyPrinter::Print(const char* string) {
char buf[2];
buf[1] = 0;
while ((buf[0] = *string++)) {
if (buf[0] == '\"') {
void QuoteEscapingPrettyPrinter::Print(const void* ptr) { wrapped_.Print(ptr); }

void HtmlEscapingPrettyPrinter::Print(absl::string_view string) {
for (char ch : string) {
if (ch == '\"') {
wrapped_.Print("&quot;");
} else if (buf[0] == '&') {
} else if (ch == '&') {
wrapped_.Print("&amp;");
} else if (buf[0] == '<') {
} else if (ch == '<') {
wrapped_.Print("&lt;");
} else if (buf[0] == '>') {
} else if (ch == '>') {
wrapped_.Print("&gt;");
} else {
wrapped_.Print(buf);
wrapped_.Print({&ch, 1});
}
}
}

void HtmlEscapingPrettyPrinter::Print(const char* string) {
Print(absl::string_view(string));
}

void HtmlEscapingPrettyPrinter::Print(const void* ptr) { wrapped_.Print(ptr); }

} // namespace verifier
Expand Down
29 changes: 15 additions & 14 deletions kythe/cxx/verifier/pretty_printer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@
#define KYTHE_CXX_VERIFIER_PRETTY_PRINTER_H_

#include <sstream>
#include <string>

#include "absl/strings/string_view.h"

namespace kythe {
namespace verifier {
Expand All @@ -27,7 +28,7 @@ namespace verifier {
class PrettyPrinter {
public:
/// \brief Prints `string`.
virtual void Print(const std::string& string) = 0;
virtual void Print(absl::string_view string) = 0;

/// \brief Prints `string`.
virtual void Print(const char* string) = 0;
Expand All @@ -41,9 +42,9 @@ class PrettyPrinter {
/// \brief A `PrettyPrinter` using a `string` as its backing store.
class StringPrettyPrinter : public PrettyPrinter {
public:
/// \copydoc PrettyPrinter::Print(const std::string&)
void Print(const std::string& string) override;
/// \copydoc PrettyPrinter::Print(const char *)
/// \copydoc PrettyPrinter::Print(absl::string_view)
void Print(absl::string_view string) override;
/// \copydoc PrettyPrinter::Print(const char*)
void Print(const char* string) override;
/// \copydoc PrettyPrinter::Print(const void *)
void Print(const void* ptr) override;
Expand All @@ -60,9 +61,9 @@ class FileHandlePrettyPrinter : public PrettyPrinter {
public:
/// \param file The file handle to print to.
explicit FileHandlePrettyPrinter(FILE* file) : file_(file) {}
/// \copydoc PrettyPrinter::Print(const std::string&)
void Print(const std::string& string) override;
/// \copydoc PrettyPrinter::Print(const char *)
/// \copydoc PrettyPrinter::Print(absl::string_view)
void Print(absl::string_view string) override;
/// \copydoc PrettyPrinter::Print(const char*)
void Print(const char* string) override;
/// \copydoc PrettyPrinter::Print(const void *)
void Print(const void* ptr) override;
Expand All @@ -79,9 +80,9 @@ class QuoteEscapingPrettyPrinter : public PrettyPrinter {
/// sent.
explicit QuoteEscapingPrettyPrinter(PrettyPrinter& wrapped)
: wrapped_(wrapped) {}
/// \copydoc PrettyPrinter::Print(const std::string&)
void Print(const std::string& string) override;
/// \copydoc PrettyPrinter::Print(const char *)
/// \copydoc PrettyPrinter::Print(absl::string_view)
void Print(absl::string_view string) override;
/// \copydoc PrettyPrinter::Print(const char*)
void Print(const char* string) override;
/// \copydoc PrettyPrinter::Print(const void *)
void Print(const void* ptr) override;
Expand All @@ -98,9 +99,9 @@ class HtmlEscapingPrettyPrinter : public PrettyPrinter {
/// sent.
explicit HtmlEscapingPrettyPrinter(PrettyPrinter& wrapped)
: wrapped_(wrapped) {}
/// \copydoc PrettyPrinter::Print(const std::string&)
void Print(const std::string& string) override;
/// \copydoc PrettyPrinter::Print(const char *)
/// \copydoc PrettyPrinter::Print(absl::string_view)
void Print(absl::string_view string) override;
/// \copydoc PrettyPrinter::Print(const char*)
void Print(const char* string) override;
/// \copydoc PrettyPrinter::Print(const void *)
void Print(const void* ptr) override;
Expand Down
60 changes: 46 additions & 14 deletions kythe/cxx/verifier/verifier.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <unistd.h>

#include "absl/memory/memory.h"
#include "absl/strings/strip.h"
#include "assertions.h"
#include "glog/logging.h"
#include "google/protobuf/text_format.h"
Expand Down Expand Up @@ -1590,11 +1591,42 @@ void Verifier::DumpAsDot() {
}
return GetLabel(node).empty();
};

std::sort(facts_.begin(), facts_.end(), GraphvizSortOrder);
FileHandlePrettyPrinter printer(stdout);
QuoteEscapingPrettyPrinter quote_printer(printer);
HtmlEscapingPrettyPrinter html_printer(printer);
FileHandlePrettyPrinter dprinter(stderr);

auto PrintQuotedNodeId = [&](AstNode* node) {
printer.Print("\"");
if (std::string label = GetLabel(node);
show_labeled_vnames_ || label.empty()) {
node->Dump(symbol_table_, &quote_printer);
} else {
quote_printer.Print(label);
}
printer.Print("\"");
};

auto FactName = [this](AstNode* node) {
StringPrettyPrinter printer;
node->Dump(symbol_table_, &printer);
if (show_fact_prefix_) {
return printer.str();
}
return std::string(absl::StripPrefix(printer.str(), "/kythe/"));
};

auto EdgeName = [this](AstNode* node) {
StringPrettyPrinter printer;
node->Dump(symbol_table_, &printer);
if (show_fact_prefix_) {
return printer.str();
}
return std::string(absl::StripPrefix(printer.str(), "/kythe/edge/"));
};

printer.Print("digraph G {\n");
for (size_t i = 0; i < facts_.size(); ++i) {
AstNode* fact = facts_[i];
Expand All @@ -1611,9 +1643,7 @@ void Verifier::DumpAsDot() {
if (ElideNode(t->element(0))) {
continue;
}
printer.Print("\"");
t->element(0)->Dump(symbol_table_, &quote_printer);
printer.Print("\"");
PrintQuotedNodeId(t->element(0));
std::string label = GetLabel(t->element(0));
if (info.kind == NodeKind::kAnchor && !show_anchors_) {
printer.Print(" [ shape=circle, label=\"@");
Expand All @@ -1626,17 +1656,21 @@ void Verifier::DumpAsDot() {
printer.Print(" [ label=<<TABLE>");
printer.Print("<TR><TD COLSPAN=\"2\">");
Tuple* nt = info.facts.front()->AsApp()->rhs()->AsTuple();
// Since all of our facts are well-formed, we know this is a vname.
nt->element(0)->AsApp()->rhs()->Dump(symbol_table_, &html_printer);
if (label.empty() || show_labeled_vnames_) {
// Since all of our facts are well-formed, we know this is a vname.
nt->element(0)->AsApp()->rhs()->Dump(symbol_table_, &html_printer);
}
if (!label.empty()) {
html_printer.Print(" = ");
if (show_labeled_vnames_) {
html_printer.Print(" = ");
}
html_printer.Print(label);
}
printer.Print("</TD></TR>");
for (AstNode* fact : info.facts) {
Tuple* nt = fact->AsApp()->rhs()->AsTuple();
printer.Print("<TR><TD>");
nt->element(3)->Dump(symbol_table_, &html_printer);
html_printer.Print(FactName(nt->element(3)));
printer.Print("</TD><TD>");
if (info.kind == NodeKind::kFile &&
EncodedIdentEqualTo(nt->element(3), text_id_)) {
Expand All @@ -1661,13 +1695,11 @@ void Verifier::DumpAsDot() {
if (ElideNode(t->element(0)) || ElideNode(t->element(2))) {
continue;
}
printer.Print("\"");
t->element(0)->Dump(symbol_table_, &quote_printer);
printer.Print("\"");
printer.Print(" -> \"");
t->element(2)->Dump(symbol_table_, &quote_printer);
printer.Print("\" [ label=\"");
t->element(1)->Dump(symbol_table_, &quote_printer);
PrintQuotedNodeId(t->element(0));
printer.Print(" -> ");
PrintQuotedNodeId(t->element(2));
printer.Print(" [ label=\"");
quote_printer.Print(EdgeName(t->element(1)));
if (t->element(4) != empty_string_id()) {
printer.Print(".");
t->element(4)->Dump(symbol_table_, &quote_printer);
Expand Down
12 changes: 12 additions & 0 deletions kythe/cxx/verifier/verifier.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,12 @@ class Verifier {
/// \brief Show anchor locations in graph dumps (instead of @).
void ShowAnchors() { show_anchors_ = true; }

/// \brief Show VNames for nodes which also have labels in graph dumps.
void ShowLabeledVnames() { show_labeled_vnames_ = true; }

/// \brief Show the /kythe and /kythe/edge prefixes in graph dumps.
void ShowFactPrefix() { show_fact_prefix_ = true; }

/// \brief Elide unlabeled nodes from graph dumps.
void ElideUnlabeled() { show_unlabeled_ = false; }

Expand Down Expand Up @@ -348,6 +354,12 @@ class Verifier {
/// If true, show unlabeled nodes in graph dumps.
bool show_unlabeled_ = true;

/// If true, show VNames for labeled nodes in graph dumps.
bool show_labeled_vnames_ = false;

/// If true, include the /kythe and /kythe/edge prefix on facts and edges.
bool show_fact_prefix_ = false;

/// Identifier for MarkedSource child edges.
AstNode* marked_source_child_id_;

Expand Down
12 changes: 12 additions & 0 deletions kythe/cxx/verifier/verifier_main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ ABSL_FLAG(std::string, goal_regex, "",
ABSL_FLAG(bool, convert_marked_source, false,
"Convert MarkedSource-valued facts to subgraphs.");
ABSL_FLAG(bool, show_anchors, false, "Show anchor locations instead of @s");
ABSL_FLAG(bool, show_vnames, true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if these flag names (as well as other graphviz-related flags) ought to have a dot_ or graphviz_ (or gv_) prefix

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly? In theory they could apply to the JSON dumps as well (but don't currently).

"Show VNames for nodes which also have labels.");
ABSL_FLAG(bool, show_fact_prefix, true,
"Include the /kythe or /kythe/edge prefix on facts and edges.");
ABSL_FLAG(bool, file_vnames, true,
"Find file vnames by matching file content.");
ABSL_FLAG(bool, use_fast_solver, false,
Expand Down Expand Up @@ -110,10 +114,18 @@ invocation and rule syntax.
v.ShowAnchors();
}

if (absl::GetFlag(FLAGS_show_vnames)) {
v.ShowLabeledVnames();
}

if (!absl::GetFlag(FLAGS_file_vnames)) {
v.IgnoreFileVnames();
}

if (absl::GetFlag(FLAGS_show_fact_prefix)) {
v.ShowFactPrefix();
}

v.UseFastSolver(absl::GetFlag(FLAGS_use_fast_solver));

std::string dbname = "database";
Expand Down