| //===- 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. | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 | // | 
 | // This diagnostic tool  | 
 | // | 
 | //===----------------------------------------------------------------------===// | 
 |  | 
 | #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/ADT/StringMap.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 void printUsage() { | 
 |   llvm::errs() << "Usage: diagtool tree [--flags-only] [<diagnostic-group>]\n"; | 
 | } | 
 |  | 
 | static bool showColors(llvm::raw_ostream &out) { | 
 |   if (&out != &llvm::errs() && &out != &llvm::outs()) | 
 |     return false; | 
 |   return llvm::errs().is_displayed() && llvm::outs().is_displayed(); | 
 | } | 
 |  | 
 | static void setColor(bool ShowColors, llvm::raw_ostream &out, | 
 |                      llvm::raw_ostream::Colors Color) { | 
 |   if (ShowColors) | 
 |     out << llvm::sys::Process::OutputColor(Color, false, false); | 
 | } | 
 |  | 
 | static void resetColor(bool ShowColors, llvm::raw_ostream &out) { | 
 |   if (ShowColors) | 
 |     out << llvm::sys::Process::ResetColor(); | 
 | } | 
 |  | 
 | static clang::DiagnosticsEngine::Level getLevel(unsigned DiagID) { | 
 |   // FIXME: This feels like a hack. | 
 |   static clang::DiagnosticsEngine Diags(new DiagnosticIDs, | 
 |                                         new DiagnosticOptions); | 
 |   return Diags.getDiagnosticLevel(DiagID, SourceLocation()); | 
 | } | 
 |  | 
 | static void printGroup(llvm::raw_ostream &out, const GroupRecord &Group, | 
 |                        bool FlagsOnly, unsigned Indent = 0) { | 
 |   out.indent(Indent * 2); | 
 |    | 
 |   bool ShowColors = showColors(out); | 
 |   setColor(ShowColors, out, llvm::raw_ostream::YELLOW); | 
 |   out << "-W" << Group.getName() << "\n"; | 
 |   resetColor(ShowColors, out); | 
 |    | 
 |   ++Indent; | 
 |   for (GroupRecord::subgroup_iterator I = Group.subgroup_begin(), | 
 |                                       E = Group.subgroup_end(); | 
 |        I != E; ++I) { | 
 |     printGroup(out, *I, FlagsOnly, Indent); | 
 |   } | 
 |  | 
 |   if (!FlagsOnly) { | 
 |     for (GroupRecord::diagnostics_iterator I = Group.diagnostics_begin(), | 
 |                                            E = Group.diagnostics_end(); | 
 |          I != E; ++I) { | 
 |       if (ShowColors) { | 
 |         if (getLevel(I->DiagID) != DiagnosticsEngine::Ignored) { | 
 |           setColor(ShowColors, out, llvm::raw_ostream::GREEN); | 
 |         } | 
 |       } | 
 |       out.indent(Indent * 2); | 
 |       out << I->getName(); | 
 |       resetColor(ShowColors, out); | 
 |       out << "\n"; | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | static int showGroup(llvm::raw_ostream &out, StringRef RootGroup, | 
 |                      bool FlagsOnly) { | 
 |   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(out, *Found, FlagsOnly); | 
 |    | 
 |   return 0; | 
 | } | 
 |  | 
 | static int showAll(llvm::raw_ostream &out, bool FlagsOnly) { | 
 |   ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups(); | 
 |   llvm::DenseSet<unsigned> NonRootGroupIDs; | 
 |  | 
 |   for (ArrayRef<GroupRecord>::iterator I = AllGroups.begin(), | 
 |                                        E = AllGroups.end(); | 
 |        I != E; ++I) { | 
 |     for (GroupRecord::subgroup_iterator SI = I->subgroup_begin(), | 
 |                                         SE = I->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(out, AllGroups[i], FlagsOnly); | 
 |   } | 
 |  | 
 |   return 0; | 
 | } | 
 |  | 
 | int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) { | 
 |   // First check our one flag (--flags-only). | 
 |   bool FlagsOnly = false; | 
 |   if (argc > 0) { | 
 |     StringRef FirstArg(*argv); | 
 |     if (FirstArg.equals("--flags-only")) { | 
 |       FlagsOnly = 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; | 
 |   } | 
 |  | 
 |   if (showColors(out)) { | 
 |     out << '\n'; | 
 |     setColor(true, out, llvm::raw_ostream::GREEN); | 
 |     out << "GREEN"; | 
 |     resetColor(true, out); | 
 |     out << " = enabled by default\n\n"; | 
 |   } | 
 |    | 
 |   if (ShowAll) | 
 |     return showAll(out, FlagsOnly); | 
 |  | 
 |   return showGroup(out, RootGroup, FlagsOnly); | 
 | } | 
 |  |