diff options
author | Max Moroz <mmoroz@chromium.org> | 2018-04-09 15:20:35 +0000 |
---|---|---|
committer | Max Moroz <mmoroz@chromium.org> | 2018-04-09 15:20:35 +0000 |
commit | 4220f89107c49e7db2247e575263ccd752cdf442 (patch) | |
tree | 2af9607851ab1d140de7fccb0507b4ffab8f0de5 /llvm | |
parent | ea9773ac69389c6eac82384b3cf98ceb774ff740 (diff) | |
download | bcm5719-llvm-4220f89107c49e7db2247e575263ccd752cdf442.tar.gz bcm5719-llvm-4220f89107c49e7db2247e575263ccd752cdf442.zip |
[llvm-cov] Implement -ignore-filename-regex= option for excluding source files.
Summary:
The option is helpful for large projects where it's not feasible to specify sources which
user would like to see in the report. Instead, it allows to black-list specific sources via
regular expressions (e.g. now it's possible to skip all files that have "test" in its name).
This also partially fixes https://bugs.llvm.org/show_bug.cgi?id=34277
Reviewers: vsk, morehouse, liaoyuke
Reviewed By: vsk
Subscribers: kcc, mgorny, llvm-commits
Differential Revision: https://reviews.llvm.org/D43907
llvm-svn: 329581
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/docs/CommandGuide/llvm-cov.rst | 12 | ||||
-rw-r--r-- | llvm/test/tools/llvm-cov/ignore-filename-regex.test | 71 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CodeCoverage.cpp | 27 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageExporter.h | 3 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageExporterJson.cpp | 13 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageExporterJson.h | 2 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageFilters.cpp | 12 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageFilters.h | 9 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageReport.cpp | 10 | ||||
-rw-r--r-- | llvm/tools/llvm-cov/CoverageReport.h | 3 |
10 files changed, 146 insertions, 16 deletions
diff --git a/llvm/docs/CommandGuide/llvm-cov.rst b/llvm/docs/CommandGuide/llvm-cov.rst index 85c8dde6496..8e9c78c23a1 100644 --- a/llvm/docs/CommandGuide/llvm-cov.rst +++ b/llvm/docs/CommandGuide/llvm-cov.rst @@ -246,6 +246,10 @@ OPTIONS Show code coverage only for functions that match the given regular expression. +.. option:: -ignore-filename-regex=<PATTERN> + + Skip source code files with file paths that match the given regular expression. + .. option:: -format=<FORMAT> Use the specified output format. The supported formats are: "text", "html". @@ -351,6 +355,10 @@ OPTIONS Show statistics for all function instantiations. Defaults to false. +.. option:: -ignore-filename-regex=<PATTERN> + + Skip source code files with file paths that match the given regular expression. + .. program:: llvm-cov export .. _llvm-cov-export: @@ -390,3 +398,7 @@ OPTIONS will not export coverage information for smaller units such as individual functions or regions. The result will be the same as produced by :program: `llvm-cov report` command, but presented in JSON format rather than text. + +.. option:: -ignore-filename-regex=<PATTERN> + + Skip source code files with file paths that match the given regular expression. diff --git a/llvm/test/tools/llvm-cov/ignore-filename-regex.test b/llvm/test/tools/llvm-cov/ignore-filename-regex.test new file mode 100644 index 00000000000..b8c15da281c --- /dev/null +++ b/llvm/test/tools/llvm-cov/ignore-filename-regex.test @@ -0,0 +1,71 @@ +######################## +# Test "report" command. +######################## +# Ignore all header files. +RUN: llvm-cov report -instr-profile %S/Inputs/sources_specified/main.profdata \ +RUN: -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*\.h$' \ +RUN: %S/Inputs/sources_specified/main.covmapping \ +RUN: | FileCheck -check-prefix=REPORT_IGNORE_HEADERS %s + +REPORT_IGNORE_HEADERS-NOT: {{.*}}dec.h{{.*}} +REPORT_IGNORE_HEADERS-NOT: {{.*}}inc.h{{.*}} +REPORT_IGNORE_HEADERS-NOT: {{.*}}abs.h{{.*}} +REPORT_IGNORE_HEADERS: {{^}}TOTAL 1{{.*}}100.00%{{$}} + +# Ignore all files from "extra" directory. +RUN: llvm-cov report -instr-profile %S/Inputs/sources_specified/main.profdata \ +RUN: -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*extra[/\\].*' \ +RUN: %S/Inputs/sources_specified/main.covmapping \ +RUN: | FileCheck -check-prefix=REPORT_IGNORE_DIR %s + +REPORT_IGNORE_DIR-NOT: {{.*}}extra{{[/\\]}}dec.h{{.*}} +REPORT_IGNORE_DIR-NOT: {{.*}}extra{{[/\\]}}inc.h{{.*}} +REPORT_IGNORE_DIR: {{.*}}abs.h{{.*}} +REPORT_IGNORE_DIR: {{.*}}main.cc{{.*}} +REPORT_IGNORE_DIR: {{^}}TOTAL 5{{.*}}100.00%{{$}} + +# Ignore all files from "extra" directory even when SOURCES specified. +RUN: llvm-cov report -instr-profile %S/Inputs/sources_specified/main.profdata \ +RUN: -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*extra[/\\].*' \ +RUN: %S/Inputs/sources_specified/main.covmapping \ +RUN: %S/Inputs/sources_specified/extra %S/Inputs/sources_specified/abs.h \ +RUN: | FileCheck -check-prefix=REPORT_IGNORE_DIR_WITH_SOURCES %s + +REPORT_IGNORE_DIR_WITH_SOURCES-NOT: {{.*}}extra{{[/\\]}}dec.h{{.*}} +REPORT_IGNORE_DIR_WITH_SOURCES-NOT: {{.*}}extra{{[/\\]}}inc.h{{.*}} +REPORT_IGNORE_DIR_WITH_SOURCES-NOT: {{.*}}main.cc{{.*}} +REPORT_IGNORE_DIR_WITH_SOURCES: {{.*}}abs.h{{.*}} +REPORT_IGNORE_DIR_WITH_SOURCES: {{^}}TOTAL 4{{.*}}100.00%{{$}} + +######################## +# Test "show" command. +######################## +# Ignore all ".cc" files. +RUN: llvm-cov show -instr-profile %S/Inputs/sources_specified/main.profdata \ +RUN: -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*\.cc$' \ +RUN: %S/Inputs/sources_specified/main.covmapping \ +RUN: | FileCheck -check-prefix=SHOW_IGNORE_CC %s + +# Order of files may differ, check that there are 3 files and not abs.h. +SHOW_IGNORE_CC-NOT: {{.*}}main.cc{{.*}} +SHOW_IGNORE_CC: {{.*}}sources_specified{{.*}} +SHOW_IGNORE_CC: {{.*}}sources_specified{{.*}} +SHOW_IGNORE_CC: {{.*}}sources_specified{{.*}} + +######################## +# Test "export" command. +######################## +# Use a temp .json file as output in a single line. Ignore headers that have +# name in a format of 3 symbols followed by ".h". +RUN: llvm-cov export -instr-profile %S/Inputs/sources_specified/main.profdata \ +RUN: -path-equivalence=/tmp,%S/Inputs -ignore-filename-regex='.*...\.h$' \ +RUN: %S/Inputs/sources_specified/main.covmapping \ +RUN: > %t.export.json + +RUN: FileCheck -check-prefix=NO-EXPORT_IGNORE_3_SYMBOLS_H %s < %t.export.json +RUN: FileCheck -check-prefix=EXPORT_IGNORE_3_SYMBOLS_H %s < %t.export.json + +NO-EXPORT_IGNORE_3_SYMBOLS_H-NOT: {{"filename":"(/|\\\\)tmp(/|\\\\)sources_specified(/|\\\\)abs.h"}} +NO-EXPORT_IGNORE_3_SYMBOLS_H-NOT: {{"filename":"(/|\\\\)tmp(/|\\\\)sources_specified(/|\\\\)inc.h"}} +NO-EXPORT_IGNORE_3_SYMBOLS_H-NOT: {{"filename":"(/|\\\\)tmp(/|\\\\)sources_specified(/|\\\\)dec.h"}} +EXPORT_IGNORE_3_SYMBOLS_H: {{"filename":"(/|\\\\)tmp(/|\\\\)sources_specified(/|\\\\)main.cc"}} diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp index 2cfe02b3eb0..430cb0b50c9 100644 --- a/llvm/tools/llvm-cov/CodeCoverage.cpp +++ b/llvm/tools/llvm-cov/CodeCoverage.cpp @@ -126,6 +126,7 @@ private: std::vector<StringRef> ObjectFilenames; CoverageViewOptions ViewOpts; CoverageFiltersMatchAll Filters; + CoverageFilters IgnoreFilenameFilters; /// The path to the indexed profile. std::string PGOFilename; @@ -189,7 +190,8 @@ void CodeCoverageTool::addCollectedPath(const std::string &Path) { return; } sys::path::remove_dots(EffectivePath, /*remove_dot_dots=*/true); - SourceFiles.emplace_back(EffectivePath.str()); + if (!IgnoreFilenameFilters.matchesFilename(EffectivePath)) + SourceFiles.emplace_back(EffectivePath.str()); } void CodeCoverageTool::collectPaths(const std::string &Path) { @@ -597,6 +599,12 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { "regular expression"), cl::ZeroOrMore, cl::cat(FilteringCategory)); + cl::list<std::string> IgnoreFilenameRegexFilters( + "ignore-filename-regex", cl::Optional, + cl::desc("Skip source code files with file paths that match the given " + "regular expression"), + cl::ZeroOrMore, cl::cat(FilteringCategory)); + cl::opt<double> RegionCoverageLtFilter( "region-coverage-lt", cl::Optional, cl::desc("Show code coverage only for functions with region coverage " @@ -714,6 +722,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { llvm::make_unique<NameRegexCoverageFilter>(Regex)); Filters.push_back(std::move(NameFilterer)); } + if (RegionCoverageLtFilter.getNumOccurrences() || RegionCoverageGtFilter.getNumOccurrences() || LineCoverageLtFilter.getNumOccurrences() || @@ -734,6 +743,11 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { Filters.push_back(std::move(StatFilterer)); } + // Create the ignore filename filters. + for (const auto &RE : IgnoreFilenameRegexFilters) + IgnoreFilenameFilters.push_back( + llvm::make_unique<NameRegexCoverageFilter>(RE)); + if (!Arches.empty()) { for (const std::string &Arch : Arches) { if (Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) { @@ -748,6 +762,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) { } } + // IgnoreFilenameFilters are applied even when InputSourceFiles specified. for (const std::string &File : InputSourceFiles) collectPaths(File); @@ -862,8 +877,10 @@ int CodeCoverageTool::doShow(int argc, const char **argv, if (SourceFiles.empty()) // Get the source files from the function coverage mapping. - for (StringRef Filename : Coverage->getUniqueSourceFiles()) - SourceFiles.push_back(Filename); + for (StringRef Filename : Coverage->getUniqueSourceFiles()) { + if (!IgnoreFilenameFilters.matchesFilename(Filename)) + SourceFiles.push_back(Filename); + } // Create an index out of the source files. if (ViewOpts.hasOutputDirectory()) { @@ -962,7 +979,7 @@ int CodeCoverageTool::doReport(int argc, const char **argv, CoverageReport Report(ViewOpts, *Coverage.get()); if (!ShowFunctionSummaries) { if (SourceFiles.empty()) - Report.renderFileReports(llvm::outs()); + Report.renderFileReports(llvm::outs(), IgnoreFilenameFilters); else Report.renderFileReports(llvm::outs(), SourceFiles); } else { @@ -998,7 +1015,7 @@ int CodeCoverageTool::doExport(int argc, const char **argv, auto Exporter = CoverageExporterJson(*Coverage.get(), ViewOpts, outs()); if (SourceFiles.empty()) - Exporter.renderRoot(); + Exporter.renderRoot(IgnoreFilenameFilters); else Exporter.renderRoot(SourceFiles); diff --git a/llvm/tools/llvm-cov/CoverageExporter.h b/llvm/tools/llvm-cov/CoverageExporter.h index af9c8f062e4..898e9755652 100644 --- a/llvm/tools/llvm-cov/CoverageExporter.h +++ b/llvm/tools/llvm-cov/CoverageExporter.h @@ -14,6 +14,7 @@ #ifndef LLVM_COV_COVERAGEEXPORTER_H #define LLVM_COV_COVERAGEEXPORTER_H +#include "CoverageFilters.h" #include "CoverageSummaryInfo.h" #include "CoverageViewOptions.h" #include "llvm/ProfileData/Coverage/CoverageMapping.h" @@ -40,7 +41,7 @@ public: virtual ~CoverageExporter(){}; /// \brief Render the CoverageMapping object. - virtual void renderRoot() = 0; + virtual void renderRoot(const CoverageFilters &IgnoreFilenameFilters) = 0; /// \brief Render the CoverageMapping object for specified source files. virtual void renderRoot(const std::vector<std::string> &SourceFiles) = 0; diff --git a/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/llvm/tools/llvm-cov/CoverageExporterJson.cpp index 3621f9ab97f..fc631ac6d83 100644 --- a/llvm/tools/llvm-cov/CoverageExporterJson.cpp +++ b/llvm/tools/llvm-cov/CoverageExporterJson.cpp @@ -117,10 +117,13 @@ void CoverageExporterJson::emitArrayEnd() { OS << "]"; } -void CoverageExporterJson::renderRoot() { +void CoverageExporterJson::renderRoot( + const CoverageFilters &IgnoreFilenameFilters) { std::vector<std::string> SourceFiles; - for (StringRef SF : Coverage.getUniqueSourceFiles()) - SourceFiles.emplace_back(SF); + for (StringRef SF : Coverage.getUniqueSourceFiles()) { + if (!IgnoreFilenameFilters.matchesFilename(SF)) + SourceFiles.emplace_back(SF); + } renderRoot(SourceFiles); } @@ -218,11 +221,11 @@ void CoverageExporterJson::renderFiles( void CoverageExporterJson::renderFile(const std::string &Filename, const FileCoverageSummary &FileReport) { - // Start File. + // Start File. emitDictStart(); emitDictElement("filename", Filename); - + if (!Options.ExportSummaryOnly) { // Calculate and render detailed coverage information for given file. auto FileCoverage = Coverage.getCoverageForFile(Filename); diff --git a/llvm/tools/llvm-cov/CoverageExporterJson.h b/llvm/tools/llvm-cov/CoverageExporterJson.h index 4631e94d535..afab8a89e29 100644 --- a/llvm/tools/llvm-cov/CoverageExporterJson.h +++ b/llvm/tools/llvm-cov/CoverageExporterJson.h @@ -101,7 +101,7 @@ public: const CoverageViewOptions &Options, raw_ostream &OS); /// \brief Render the CoverageMapping object. - void renderRoot() override; + void renderRoot(const CoverageFilters &IgnoreFilenameFilters) override; /// \brief Render the CoverageMapping object for specified source files. void renderRoot(const std::vector<std::string> &SourceFiles) override; diff --git a/llvm/tools/llvm-cov/CoverageFilters.cpp b/llvm/tools/llvm-cov/CoverageFilters.cpp index 441179601dc..4dd0f552c7e 100644 --- a/llvm/tools/llvm-cov/CoverageFilters.cpp +++ b/llvm/tools/llvm-cov/CoverageFilters.cpp @@ -30,6 +30,10 @@ bool NameRegexCoverageFilter::matches( return llvm::Regex(Regex).match(Function.Name); } +bool NameRegexCoverageFilter::matchesFilename(StringRef Filename) const { + return llvm::Regex(Regex).match(Filename); +} + bool NameWhitelistCoverageFilter::matches( const coverage::CoverageMapping &, const coverage::FunctionRecord &Function) const { @@ -63,6 +67,14 @@ bool CoverageFilters::matches(const coverage::CoverageMapping &CM, return false; } +bool CoverageFilters::matchesFilename(StringRef Filename) const { + for (const auto &Filter : Filters) { + if (Filter->matchesFilename(Filename)) + return true; + } + return false; +} + bool CoverageFiltersMatchAll::matches( const coverage::CoverageMapping &CM, const coverage::FunctionRecord &Function) const { diff --git a/llvm/tools/llvm-cov/CoverageFilters.h b/llvm/tools/llvm-cov/CoverageFilters.h index aeaf61de173..eacc6d2d489 100644 --- a/llvm/tools/llvm-cov/CoverageFilters.h +++ b/llvm/tools/llvm-cov/CoverageFilters.h @@ -32,6 +32,11 @@ public: const coverage::FunctionRecord &Function) const { return true; } + + /// \brief Return true if the filename passes the requirements of this filter. + virtual bool matchesFilename(StringRef Filename) const { + return true; + } }; /// \brief Matches functions that contain a specific string in their name. @@ -54,6 +59,8 @@ public: bool matches(const coverage::CoverageMapping &CM, const coverage::FunctionRecord &Function) const override; + + bool matchesFilename(StringRef Filename) const override; }; /// \brief Matches functions whose name appears in a SpecialCaseList in the @@ -133,6 +140,8 @@ public: bool matches(const coverage::CoverageMapping &CM, const coverage::FunctionRecord &Function) const override; + + bool matchesFilename(StringRef Filename) const override; }; /// \brief A collection of filters. diff --git a/llvm/tools/llvm-cov/CoverageReport.cpp b/llvm/tools/llvm-cov/CoverageReport.cpp index aafdc433775..5d892202f0d 100644 --- a/llvm/tools/llvm-cov/CoverageReport.cpp +++ b/llvm/tools/llvm-cov/CoverageReport.cpp @@ -379,10 +379,14 @@ std::vector<FileCoverageSummary> CoverageReport::prepareFileReports( return FileReports; } -void CoverageReport::renderFileReports(raw_ostream &OS) const { +void CoverageReport::renderFileReports( + raw_ostream &OS, const CoverageFilters &IgnoreFilenameFilters) const { std::vector<std::string> UniqueSourceFiles; - for (StringRef SF : Coverage.getUniqueSourceFiles()) - UniqueSourceFiles.emplace_back(SF.str()); + for (StringRef SF : Coverage.getUniqueSourceFiles()) { + // Apply ignore source files filters. + if (!IgnoreFilenameFilters.matchesFilename(SF)) + UniqueSourceFiles.emplace_back(SF.str()); + } renderFileReports(OS, UniqueSourceFiles); } diff --git a/llvm/tools/llvm-cov/CoverageReport.h b/llvm/tools/llvm-cov/CoverageReport.h index f90729b910a..8864d309fe9 100644 --- a/llvm/tools/llvm-cov/CoverageReport.h +++ b/llvm/tools/llvm-cov/CoverageReport.h @@ -53,7 +53,8 @@ public: const CoverageFilter *Filters); /// Render file reports for every unique file in the coverage mapping. - void renderFileReports(raw_ostream &OS) const; + void renderFileReports(raw_ostream &OS, + const CoverageFilters &IgnoreFilenameFilters) const; /// Render file reports for the files specified in \p Files. void renderFileReports(raw_ostream &OS, ArrayRef<std::string> Files) const; |