Files
clang-p2996/clang/tools/diagtool/TreeView.cpp
Jonas Devlieghere 5dc87861d6 [diagtool] Change default tree behavior to print only flags
This patch changes the default behavior of `diagtool tree` to only
display warning flags and not the internal warnings flags. The latter is
an implementation detail of the compiler and usually not what the users
wants.

Furthermore, flags that are enabled by default are now also printed in
green. Originally, this was only the case for the diagnostic names.

Differential revision: https://reviews.llvm.org/D37390

llvm-svn: 312546
2017-09-05 18:04:40 +00:00

193 lines
4.8 KiB
C++

//===- TreeView.cpp - diagtool tool for printing warning flags ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "DiagTool.h"
#include "DiagnosticNames.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/Basic/AllDiagnostics.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/DiagnosticOptions.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/Process.h"
DEF_DIAGTOOL("tree", "Show warning flags in a tree view", TreeView)
using namespace clang;
using namespace diagtool;
static bool hasColors(const llvm::raw_ostream &out) {
if (&out != &llvm::errs() && &out != &llvm::outs())
return false;
return llvm::errs().is_displayed() && llvm::outs().is_displayed();
}
class TreePrinter {
public:
llvm::raw_ostream &out;
const bool ShowColors;
bool Internal;
TreePrinter(llvm::raw_ostream &out)
: out(out), ShowColors(hasColors(out)), Internal(false) {}
void setColor(llvm::raw_ostream::Colors Color) {
if (ShowColors)
out << llvm::sys::Process::OutputColor(Color, false, false);
}
void resetColor() {
if (ShowColors)
out << llvm::sys::Process::ResetColor();
}
static bool isIgnored(unsigned DiagID) {
// FIXME: This feels like a hack.
static clang::DiagnosticsEngine Diags(new DiagnosticIDs,
new DiagnosticOptions);
return Diags.isIgnored(DiagID, SourceLocation());
}
static bool enabledByDefault(const GroupRecord &Group) {
for (const DiagnosticRecord &DR : Group.diagnostics()) {
if (isIgnored(DR.DiagID))
return false;
}
for (const GroupRecord &GR : Group.subgroups()) {
if (!enabledByDefault(GR))
return false;
}
return true;
}
void printGroup(const GroupRecord &Group, unsigned Indent = 0) {
out.indent(Indent * 2);
if (enabledByDefault(Group))
setColor(llvm::raw_ostream::GREEN);
else
setColor(llvm::raw_ostream::YELLOW);
out << "-W" << Group.getName() << "\n";
resetColor();
++Indent;
for (const GroupRecord &GR : Group.subgroups()) {
printGroup(GR, Indent);
}
if (Internal) {
for (const DiagnosticRecord &DR : Group.diagnostics()) {
if (ShowColors && !isIgnored(DR.DiagID))
setColor(llvm::raw_ostream::GREEN);
out.indent(Indent * 2);
out << DR.getName();
resetColor();
out << "\n";
}
}
}
int showGroup(StringRef RootGroup) {
ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
if (RootGroup.size() > UINT16_MAX) {
llvm::errs() << "No such diagnostic group exists\n";
return 1;
}
const GroupRecord *Found =
std::lower_bound(AllGroups.begin(), AllGroups.end(), RootGroup);
if (Found == AllGroups.end() || Found->getName() != RootGroup) {
llvm::errs() << "No such diagnostic group exists\n";
return 1;
}
printGroup(*Found);
return 0;
}
int showAll() {
ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
llvm::DenseSet<unsigned> NonRootGroupIDs;
for (const GroupRecord &GR : AllGroups) {
for (auto SI = GR.subgroup_begin(), SE = GR.subgroup_end(); SI != SE;
++SI) {
NonRootGroupIDs.insert((unsigned)SI.getID());
}
}
assert(NonRootGroupIDs.size() < AllGroups.size());
for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) {
if (!NonRootGroupIDs.count(i))
printGroup(AllGroups[i]);
}
return 0;
}
void showKey() {
if (ShowColors) {
out << '\n';
setColor(llvm::raw_ostream::GREEN);
out << "GREEN";
resetColor();
out << " = enabled by default\n\n";
}
}
};
static void printUsage() {
llvm::errs() << "Usage: diagtool tree [--internal] [<diagnostic-group>]\n";
}
int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
// First check our one flag (--flags-only).
bool Internal = false;
if (argc > 0) {
StringRef FirstArg(*argv);
if (FirstArg.equals("--internal")) {
Internal = true;
--argc;
++argv;
}
}
bool ShowAll = false;
StringRef RootGroup;
switch (argc) {
case 0:
ShowAll = true;
break;
case 1:
RootGroup = argv[0];
if (RootGroup.startswith("-W"))
RootGroup = RootGroup.substr(2);
if (RootGroup == "everything")
ShowAll = true;
// FIXME: Handle other special warning flags, like -pedantic.
break;
default:
printUsage();
return -1;
}
TreePrinter TP(out);
TP.Internal = Internal;
TP.showKey();
return ShowAll ? TP.showAll() : TP.showGroup(RootGroup);
}