1 //===- CoverageReport.h - Code coverage report ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This class implements rendering of a code coverage report.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_COV_COVERAGEREPORT_H
14 #define LLVM_COV_COVERAGEREPORT_H
15 
16 #include "CoverageFilters.h"
17 #include "CoverageSummaryInfo.h"
18 #include "CoverageViewOptions.h"
19 #include <map>
20 
21 namespace llvm {
22 
23 class ThreadPool;
24 
25 /// Displays the code coverage report.
26 class CoverageReport {
27   const CoverageViewOptions &Options;
28   const coverage::CoverageMapping &Coverage;
29 
30   void render(const FileCoverageSummary &File, raw_ostream &OS) const;
31   void render(const FunctionCoverageSummary &Function, const DemangleCache &DC,
32               raw_ostream &OS) const;
33 
34 public:
35   CoverageReport(const CoverageViewOptions &Options,
36                  const coverage::CoverageMapping &Coverage)
37       : Options(Options), Coverage(Coverage) {}
38 
39   void renderFunctionReports(ArrayRef<std::string> Files,
40                              const DemangleCache &DC, raw_ostream &OS);
41 
42   /// Prepare file reports for the files specified in \p Files.
43   static std::vector<FileCoverageSummary>
44   prepareFileReports(const coverage::CoverageMapping &Coverage,
45                      FileCoverageSummary &Totals, ArrayRef<std::string> Files,
46                      const CoverageViewOptions &Options,
47                      const CoverageFilter &Filters = CoverageFiltersMatchAll());
48 
49   static void
50   prepareSingleFileReport(const StringRef Filename,
51                           const coverage::CoverageMapping *Coverage,
52                           const CoverageViewOptions &Options,
53                           const unsigned LCP,
54                           FileCoverageSummary *FileReport,
55                           const CoverageFilter *Filters);
56 
57   /// Render file reports for every unique file in the coverage mapping.
58   void renderFileReports(raw_ostream &OS,
59                          const CoverageFilters &IgnoreFilenameFilters) const;
60 
61   /// Render file reports for the files specified in \p Files.
62   void renderFileReports(raw_ostream &OS, ArrayRef<std::string> Files) const;
63 
64   /// Render file reports for the files specified in \p Files and the functions
65   /// in \p Filters.
66   void renderFileReports(raw_ostream &OS, ArrayRef<std::string> Files,
67                          const CoverageFiltersMatchAll &Filters) const;
68 
69   /// Render file reports with given data.
70   void renderFileReports(raw_ostream &OS,
71                          const std::vector<FileCoverageSummary> &FileReports,
72                          const FileCoverageSummary &Totals,
73                          bool ShowEmptyFiles) const;
74 };
75 
76 /// Prepare reports for every non-trivial directories (which have more than 1
77 /// source files) of the source files. This class uses template method pattern.
78 class DirectoryCoverageReport {
79 public:
80   DirectoryCoverageReport(
81       const CoverageViewOptions &Options,
82       const coverage::CoverageMapping &Coverage,
83       const CoverageFiltersMatchAll &Filters = CoverageFiltersMatchAll())
84       : Options(Options), Coverage(Coverage), Filters(Filters) {}
85 
86   virtual ~DirectoryCoverageReport() = default;
87 
88   /// Prepare file reports for each directory in \p SourceFiles. The total
89   /// report for all files is returned and its Name is set to the LCP of all
90   /// files. The size of \p SourceFiles must be greater than 1 or else the
91   /// behavior is undefined, in which case you should use
92   /// CoverageReport::prepareSingleFileReport instead. If an error occurs,
93   /// the recursion will stop immediately.
94   Expected<FileCoverageSummary>
95   prepareDirectoryReports(ArrayRef<std::string> SourceFiles);
96 
97 protected:
98   // These member variables below are used for avoiding being passed
99   // repeatedly in recursion.
100   const CoverageViewOptions &Options;
101   const coverage::CoverageMapping &Coverage;
102   const CoverageFiltersMatchAll &Filters;
103 
104   /// For calling CoverageReport::prepareSingleFileReport asynchronously
105   /// in prepareSubDirectoryReports(). It's not intended to be modified by
106   /// generateSubDirectoryReport().
107   ThreadPool *TPool;
108 
109   /// One report level may correspond to multiple directory levels as we omit
110   /// directories which have only one subentry. So we use this Stack to track
111   /// each report level's corresponding drectory level.
112   /// Each value in the stack is the LCP prefix length length of that report
113   /// level. LCPStack.front() is the root LCP. Current LCP is LCPStack.back().
114   SmallVector<unsigned, 32> LCPStack;
115 
116   // Use std::map to sort table rows in order.
117   using SubFileReports = std::map<StringRef, FileCoverageSummary>;
118   using SubDirReports =
119       std::map<StringRef,
120                std::pair<FileCoverageSummary, SmallVector<StringRef, 0>>>;
121 
122   /// This method is called when a report level is prepared during the
123   /// recursion. \p SubFiles are the reports for those files directly in the
124   /// current directory. \p SubDirs are the reports for subdirectories in
125   /// current directory. \p SubTotals is the sum of all, and its name is the
126   /// current LCP. Note that this method won't be called for trivial
127   /// directories.
128   virtual Error generateSubDirectoryReport(SubFileReports &&SubFiles,
129                                            SubDirReports &&SubDirs,
130                                            FileCoverageSummary &&SubTotals) = 0;
131 
132 private:
133   Error prepareSubDirectoryReports(const ArrayRef<StringRef> &Files,
134                                    FileCoverageSummary *Totals);
135 };
136 
137 } // end namespace llvm
138 
139 #endif // LLVM_COV_COVERAGEREPORT_H
140