Index: test/tools/llvm-cov/sources-specified.test =================================================================== --- test/tools/llvm-cov/sources-specified.test +++ test/tools/llvm-cov/sources-specified.test @@ -20,6 +20,20 @@ SHOW: {{.*}}sources_specified{{.*}} SHOW: {{.*}}sources_specified{{.*}} + +# Test "export" command. Use a temp .json file as output is a single line. +RUN: llvm-cov export -instr-profile %S/Inputs/sources_specified/main.profdata \ +RUN: -path-equivalence=/tmp,%S/Inputs \ +RUN: %S/Inputs/sources_specified/main.covmapping \ +RUN: %S/Inputs/sources_specified/main.cc %S/Inputs/sources_specified/extra \ +RUN: > %t.export.json + +RUN: not grep '"filename":"/tmp/sources_specified/abs.h"' %t.export.json +RUN: grep '"filename":"/tmp/sources_specified/main.cc"' %t.export.json +RUN: grep '"filename":"/tmp/sources_specified/extra/dec.h"' %t.export.json +RUN: grep '"filename":"/tmp/sources_specified/extra/inc.h"' %t.export.json + + Instructions for regenerating the test: # cd %S/Inputs/sources_specified Index: tools/llvm-cov/CodeCoverage.cpp =================================================================== --- tools/llvm-cov/CodeCoverage.cpp +++ tools/llvm-cov/CodeCoverage.cpp @@ -13,6 +13,7 @@ // //===----------------------------------------------------------------------===// +#include "CoverageExporterJson.h" #include "CoverageFilters.h" #include "CoverageReport.h" #include "CoverageSummaryInfo.h" @@ -113,14 +114,14 @@ typedef llvm::function_ref CommandLineParserType; - int show(int argc, const char **argv, - CommandLineParserType commandLineParser); - - int report(int argc, const char **argv, + int doShow(int argc, const char **argv, CommandLineParserType commandLineParser); - int export_(int argc, const char **argv, - CommandLineParserType commandLineParser); + int doReport(int argc, const char **argv, + CommandLineParserType commandLineParser); + + int doExport(int argc, const char **argv, + CommandLineParserType commandLineParser); std::vector ObjectFilenames; CoverageViewOptions ViewOpts; @@ -754,17 +755,17 @@ switch (Cmd) { case Show: - return show(argc, argv, commandLineParser); + return doShow(argc, argv, commandLineParser); case Report: - return report(argc, argv, commandLineParser); + return doReport(argc, argv, commandLineParser); case Export: - return export_(argc, argv, commandLineParser); + return doExport(argc, argv, commandLineParser); } return 0; } -int CodeCoverageTool::show(int argc, const char **argv, - CommandLineParserType commandLineParser) { +int CodeCoverageTool::doShow(int argc, const char **argv, + CommandLineParserType commandLineParser) { cl::OptionCategory ViewCategory("Viewing options"); @@ -931,8 +932,8 @@ return 0; } -int CodeCoverageTool::report(int argc, const char **argv, - CommandLineParserType commandLineParser) { +int CodeCoverageTool::doReport(int argc, const char **argv, + CommandLineParserType commandLineParser) { cl::opt ShowFunctionSummaries( "show-functions", cl::Optional, cl::init(false), cl::desc("Show coverage summaries for each function")); @@ -968,8 +969,8 @@ return 0; } -int CodeCoverageTool::export_(int argc, const char **argv, - CommandLineParserType commandLineParser) { +int CodeCoverageTool::doExport(int argc, const char **argv, + CommandLineParserType commandLineParser) { auto Err = commandLineParser(argc, argv); if (Err) @@ -986,7 +987,13 @@ return 1; } - exportCoverageDataToJson(*Coverage.get(), ViewOpts, outs()); + // exportCoverageDataToJson(*Coverage.get(), ViewOpts, outs()); + auto Exporter = CoverageExporterJson(*Coverage.get(), ViewOpts, outs()); + + if (SourceFiles.empty()) + Exporter.renderRoot(); + else + Exporter.renderRoot(SourceFiles); return 0; } Index: tools/llvm-cov/CoverageExporter.h =================================================================== --- /dev/null +++ tools/llvm-cov/CoverageExporter.h @@ -0,0 +1,50 @@ +//===- CoverageExporter.h - Code coverage exporter ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a code coverage export functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_COV_COVERAGEEXPORTER_H +#define LLVM_COV_COVERAGEEXPORTER_H + +#include "CoverageSummaryInfo.h" +#include "CoverageViewOptions.h" +#include "llvm/ProfileData/Coverage/CoverageMapping.h" + +namespace llvm { + +/// \brief Exports the code coverage information. +class CoverageExporter { +protected: + /// \brief The full CoverageMapping object to export. + const coverage::CoverageMapping &Coverage; + + const CoverageViewOptions &Options; + + /// \brief Output stream to print JSON to. + raw_ostream &OS; + + CoverageExporter(const coverage::CoverageMapping &CoverageMapping, + const CoverageViewOptions &Options, raw_ostream &OS) + : Coverage(CoverageMapping), Options(Options), OS(OS) {} + +public: + virtual ~CoverageExporter(){}; + + /// \brief Render the CoverageMapping object. + virtual void renderRoot() = 0; + + /// \brief Render the CoverageMapping object for specified source files. + virtual void renderRoot(const std::vector &SourceFiles) = 0; +}; + +} // end namespace llvm + +#endif // LLVM_COV_COVERAGEEXPORTER_H Index: tools/llvm-cov/CoverageExporterJson.h =================================================================== --- /dev/null +++ tools/llvm-cov/CoverageExporterJson.h @@ -0,0 +1,108 @@ +//===- CoverageExport.h - Code coverage export ----------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a code coverage export functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_COV_COVERAGEEXPORTERJSON_H +#define LLVM_COV_COVERAGEEXPORTERJSON_H + +#include "CoverageExporter.h" +#include + +namespace llvm { + +class CoverageExporterJson : public CoverageExporter { + /// \brief States that the JSON rendering machine can be in. + enum JsonState { None, NonEmptyElement, EmptyElement }; + + /// \brief Tracks state of the JSON output. + std::stack State; + + /// \brief Emit a serialized scalar. + void emitSerialized(const int64_t Value); + + /// \brief Emit a serialized string. + void emitSerialized(const std::string &Value); + + /// \brief Emit a comma if there is a previous element to delimit. + void emitComma(); + + /// \brief Emit a starting dictionary/object character. + void emitDictStart(); + + /// \brief Emit a dictionary/object key but no value. + void emitDictKey(const std::string &Key); + + /// \brief Emit a dictionary/object key/value pair. + template + void emitDictElement(const std::string &Key, const V &Value) { + emitComma(); + emitSerialized(Key); + OS << ":"; + emitSerialized(Value); + } + + /// \brief Emit a closing dictionary/object character. + void emitDictEnd(); + + /// \brief Emit a starting array character. + void emitArrayStart(); + + /// \brief Emit an array element. + template void emitArrayElement(const V &Value) { + emitComma(); + emitSerialized(Value); + } + + /// \brief emit a closing array character. + void emitArrayEnd(); + + /// \brief Render an array of all the given functions. + void renderFunctions( + const iterator_range &Functions); + + /// \brief Render an array of all the source files, also pass back a Summary. + void renderFiles(ArrayRef SourceFiles, + ArrayRef FileReports); + + /// \brief Render a single file. + void renderFile(const coverage::CoverageData &FileCoverage, + const FileCoverageSummary &FileReport); + + /// \brief Render a CoverageSegment. + void renderSegment(const coverage::CoverageSegment &Segment); + + /// \brief Render an ExpansionRecord. + void renderExpansion(const coverage::ExpansionRecord &Expansion); + + /// \brief Render a list of CountedRegions. + void renderRegions(ArrayRef Regions); + + /// \brief Render a single CountedRegion. + void renderRegion(const coverage::CountedRegion &Region); + + /// \brief Render a FileCoverageSummary. + void renderSummary(const FileCoverageSummary &Summary); + +public: + CoverageExporterJson(const coverage::CoverageMapping &CoverageMapping, + const CoverageViewOptions &Options, raw_ostream &OS); + + /// \brief Render the CoverageMapping object. + void renderRoot() override; + + /// \brief Render the CoverageMapping object for specified source files. + void renderRoot(const std::vector &SourceFiles) override; +}; + +} // end namespace llvm + +#endif // LLVM_COV_COVERAGEEXPORTERJSON_H Index: tools/llvm-cov/CoverageExporterJson.cpp =================================================================== --- tools/llvm-cov/CoverageExporterJson.cpp +++ tools/llvm-cov/CoverageExporterJson.cpp @@ -41,11 +41,8 @@ // //===----------------------------------------------------------------------===// +#include "CoverageExporterJson.h" #include "CoverageReport.h" -#include "CoverageSummaryInfo.h" -#include "CoverageViewOptions.h" -#include "llvm/ProfileData/Coverage/CoverageMapping.h" -#include /// \brief The semantic version combined as a string. #define LLVM_COVERAGE_EXPORT_JSON_STR "2.0.0" @@ -54,381 +51,328 @@ #define LLVM_COVERAGE_EXPORT_JSON_TYPE_STR "llvm.coverage.json.export" using namespace llvm; -using namespace coverage; -class CoverageExporterJson { - const CoverageViewOptions &Options; - - /// \brief Output stream to print JSON to. - raw_ostream &OS; - - /// \brief The full CoverageMapping object to export. - const CoverageMapping &Coverage; - - /// \brief States that the JSON rendering machine can be in. - enum JsonState { None, NonEmptyElement, EmptyElement }; - - /// \brief Tracks state of the JSON output. - std::stack State; - - /// \brief Emit a serialized scalar. - void emitSerialized(const int64_t Value) { OS << Value; } - - /// \brief Emit a serialized string. - void emitSerialized(const std::string &Value) { - OS << "\""; - for (char C : Value) { - if (C != '\\') - OS << C; - else - OS << "\\\\"; - } - OS << "\""; - } - - /// \brief Emit a comma if there is a previous element to delimit. - void emitComma() { - if (State.top() == JsonState::NonEmptyElement) { - OS << ","; - } else if (State.top() == JsonState::EmptyElement) { - State.pop(); - assert((State.size() >= 1) && "Closed too many JSON elements"); - State.push(JsonState::NonEmptyElement); - } - } - - /// \brief Emit a starting dictionary/object character. - void emitDictStart() { - emitComma(); - State.push(JsonState::EmptyElement); - OS << "{"; - } - - /// \brief Emit a dictionary/object key but no value. - void emitDictKey(const std::string &Key) { - emitComma(); - emitSerialized(Key); - OS << ":"; - State.pop(); - assert((State.size() >= 1) && "Closed too many JSON elements"); - - // We do not want to emit a comma after this key. - State.push(JsonState::EmptyElement); - } - - /// \brief Emit a dictionary/object key/value pair. - template - void emitDictElement(const std::string &Key, const V &Value) { - emitComma(); - emitSerialized(Key); - OS << ":"; - emitSerialized(Value); - } - - /// \brief Emit a closing dictionary/object character. - void emitDictEnd() { - State.pop(); - assert((State.size() >= 1) && "Closed too many JSON elements"); - OS << "}"; - } +CoverageExporterJson::CoverageExporterJson( + const coverage::CoverageMapping &CoverageMapping, + const CoverageViewOptions &Options, raw_ostream &OS) + : CoverageExporter(CoverageMapping, Options, OS) { + State.push(JsonState::None); +} - /// \brief Emit a starting array character. - void emitArrayStart() { - emitComma(); - State.push(JsonState::EmptyElement); - OS << "["; - } +void CoverageExporterJson::emitSerialized(const int64_t Value) { OS << Value; } - /// \brief Emit an array element. - template void emitArrayElement(const V &Value) { - emitComma(); - emitSerialized(Value); +void CoverageExporterJson::emitSerialized(const std::string &Value) { + OS << "\""; + for (char C : Value) { + if (C != '\\') + OS << C; + else + OS << "\\\\"; } + OS << "\""; +} - /// \brief emit a closing array character. - void emitArrayEnd() { +void CoverageExporterJson::emitComma() { + if (State.top() == JsonState::NonEmptyElement) { + OS << ","; + } else if (State.top() == JsonState::EmptyElement) { State.pop(); assert((State.size() >= 1) && "Closed too many JSON elements"); - OS << "]"; + State.push(JsonState::NonEmptyElement); } +} - /// \brief Render the CoverageMapping object. - void renderRoot() { - // Start Root of JSON object. - emitDictStart(); - - emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR); - emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR); - emitDictKey("data"); +void CoverageExporterJson::emitDictStart() { + emitComma(); + State.push(JsonState::EmptyElement); + OS << "{"; +} - // Start List of Exports. - emitArrayStart(); +void CoverageExporterJson::emitDictKey(const std::string &Key) { + emitComma(); + emitSerialized(Key); + OS << ":"; + State.pop(); + assert((State.size() >= 1) && "Closed too many JSON elements"); - // Start Export. - emitDictStart(); + // We do not want to emit a comma after this key. + State.push(JsonState::EmptyElement); +} - emitDictKey("files"); +void CoverageExporterJson::emitDictEnd() { + State.pop(); + assert((State.size() >= 1) && "Closed too many JSON elements"); + OS << "}"; +} - FileCoverageSummary Totals = FileCoverageSummary("Totals"); - std::vector SourceFiles; - for (StringRef SF : Coverage.getUniqueSourceFiles()) - SourceFiles.emplace_back(SF); - auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals, - SourceFiles, Options); - renderFiles(SourceFiles, FileReports); - - // Skip functions-level information for summary-only export mode. - if (!Options.ExportSummaryOnly) { - emitDictKey("functions"); - renderFunctions(Coverage.getCoveredFunctions()); - } +void CoverageExporterJson::emitArrayStart() { + emitComma(); + State.push(JsonState::EmptyElement); + OS << "["; +} - emitDictKey("totals"); - renderSummary(Totals); +void CoverageExporterJson::emitArrayEnd() { + State.pop(); + assert((State.size() >= 1) && "Closed too many JSON elements"); + OS << "]"; +} - // End Export. - emitDictEnd(); +void CoverageExporterJson::renderRoot() { + std::vector SourceFiles; + for (StringRef SF : Coverage.getUniqueSourceFiles()) + SourceFiles.emplace_back(SF); + renderRoot(SourceFiles); +} - // End List of Exports. - emitArrayEnd(); +void CoverageExporterJson::renderRoot( + const std::vector &SourceFiles) { + // Start Root of JSON object. + emitDictStart(); + + emitDictElement("version", LLVM_COVERAGE_EXPORT_JSON_STR); + emitDictElement("type", LLVM_COVERAGE_EXPORT_JSON_TYPE_STR); + emitDictKey("data"); + + // Start List of Exports. + emitArrayStart(); + + // Start Export. + emitDictStart(); + + emitDictKey("files"); + + FileCoverageSummary Totals = FileCoverageSummary("Totals"); + auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals, + SourceFiles, Options); + renderFiles(SourceFiles, FileReports); - // End Root of JSON Object. - emitDictEnd(); - - assert((State.top() == JsonState::None) && - "All Elements In JSON were Closed"); + // Skip functions-level information for summary-only export mode. + if (!Options.ExportSummaryOnly) { + emitDictKey("functions"); + renderFunctions(Coverage.getCoveredFunctions()); } - /// \brief Render an array of all the given functions. - void - renderFunctions(const iterator_range &Functions) { - // Start List of Functions. - emitArrayStart(); + emitDictKey("totals"); + renderSummary(Totals); - for (const auto &Function : Functions) { - // Start Function. - emitDictStart(); + // End Export. + emitDictEnd(); - emitDictElement("name", Function.Name); - emitDictElement("count", Function.ExecutionCount); - emitDictKey("regions"); + // End List of Exports. + emitArrayEnd(); - renderRegions(Function.CountedRegions); + // End Root of JSON Object. + emitDictEnd(); - emitDictKey("filenames"); + assert((State.top() == JsonState::None) && + "All Elements In JSON were Closed"); +} - // Start Filenames for Function. - emitArrayStart(); +void CoverageExporterJson::renderFunctions( + const iterator_range &Functions) { + // Start List of Functions. + emitArrayStart(); - for (const auto &FileName : Function.Filenames) - emitArrayElement(FileName); + for (const auto &Function : Functions) { + // Start Function. + emitDictStart(); - // End Filenames for Function. - emitArrayEnd(); + emitDictElement("name", Function.Name); + emitDictElement("count", Function.ExecutionCount); + emitDictKey("regions"); - // End Function. - emitDictEnd(); - } + renderRegions(Function.CountedRegions); - // End List of Functions. - emitArrayEnd(); - } + emitDictKey("filenames"); - /// \brief Render an array of all the source files, also pass back a Summary. - void renderFiles(ArrayRef SourceFiles, - ArrayRef FileReports) { - // Start List of Files. + // Start Filenames for Function. emitArrayStart(); - for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) { - // Render the file. - auto FileCoverage = Coverage.getCoverageForFile(SourceFiles[I]); - renderFile(FileCoverage, FileReports[I]); - } + for (const auto &FileName : Function.Filenames) + emitArrayElement(FileName); - // End List of Files. + // End Filenames for Function. emitArrayEnd(); - } - /// \brief Render a single file. - void renderFile(const CoverageData &FileCoverage, - const FileCoverageSummary &FileReport) { - // Start File. - emitDictStart(); - - emitDictElement("filename", FileCoverage.getFilename()); - - // Skip segments and expansions for summary-only export mode. - if (!Options.ExportSummaryOnly) { - emitDictKey("segments"); - - // Start List of Segments. - emitArrayStart(); - - for (const auto &Segment : FileCoverage) - renderSegment(Segment); - - // End List of Segments. - emitArrayEnd(); - - emitDictKey("expansions"); - - // Start List of Expansions. - emitArrayStart(); - - for (const auto &Expansion : FileCoverage.getExpansions()) - renderExpansion(Expansion); - - // End List of Expansions. - emitArrayEnd(); - } - - emitDictKey("summary"); - renderSummary(FileReport); - - // End File. + // End Function. emitDictEnd(); } - /// \brief Render a CoverageSegment. - void renderSegment(const CoverageSegment &Segment) { - // Start Segment. - emitArrayStart(); - - emitArrayElement(Segment.Line); - emitArrayElement(Segment.Col); - emitArrayElement(Segment.Count); - emitArrayElement(Segment.HasCount); - emitArrayElement(Segment.IsRegionEntry); + // End List of Functions. + emitArrayEnd(); +} - // End Segment. - emitArrayEnd(); +void CoverageExporterJson::renderFiles( + ArrayRef SourceFiles, + ArrayRef FileReports) { + // Start List of Files. + emitArrayStart(); + + for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I) { + // Render the file. + auto FileCoverage = Coverage.getCoverageForFile(SourceFiles[I]); + renderFile(FileCoverage, FileReports[I]); } - /// \brief Render an ExpansionRecord. - void renderExpansion(const ExpansionRecord &Expansion) { - // Start Expansion. - emitDictStart(); + // End List of Files. + emitArrayEnd(); +} - // Mark the beginning and end of this expansion in the source file. - emitDictKey("source_region"); - renderRegion(Expansion.Region); - - // Enumerate the coverage information for the expansion. - emitDictKey("target_regions"); - renderRegions(Expansion.Function.CountedRegions); +void CoverageExporterJson::renderFile( + const coverage::CoverageData &FileCoverage, + const FileCoverageSummary &FileReport) { + // Start File. + emitDictStart(); + + emitDictElement("filename", FileCoverage.getFilename()); + + // Skip segments and expansions for summary-only export mode. + if (!Options.ExportSummaryOnly) { + emitDictKey("segments"); - emitDictKey("filenames"); - // Start List of Filenames to map the fileIDs. + // Start List of Segments. emitArrayStart(); - for (const auto &Filename : Expansion.Function.Filenames) - emitArrayElement(Filename); - // End List of Filenames. - emitArrayEnd(); - // End Expansion. - emitDictEnd(); - } - - /// \brief Render a list of CountedRegions. - void renderRegions(ArrayRef Regions) { - // Start List of Regions. - emitArrayStart(); + for (const auto &Segment : FileCoverage) + renderSegment(Segment); - for (const auto &Region : Regions) - renderRegion(Region); - - // End List of Regions. + // End List of Segments. emitArrayEnd(); - } - /// \brief Render a single CountedRegion. - void renderRegion(const CountedRegion &Region) { - // Start CountedRegion. + emitDictKey("expansions"); + + // Start List of Expansions. emitArrayStart(); - emitArrayElement(Region.LineStart); - emitArrayElement(Region.ColumnStart); - emitArrayElement(Region.LineEnd); - emitArrayElement(Region.ColumnEnd); - emitArrayElement(Region.ExecutionCount); - emitArrayElement(Region.FileID); - emitArrayElement(Region.ExpandedFileID); - emitArrayElement(Region.Kind); + for (const auto &Expansion : FileCoverage.getExpansions()) + renderExpansion(Expansion); - // End CountedRegion. + // End List of Expansions. emitArrayEnd(); } - /// \brief Render a FileCoverageSummary. - void renderSummary(const FileCoverageSummary &Summary) { - // Start Summary for the file. - emitDictStart(); + emitDictKey("summary"); + renderSummary(FileReport); - emitDictKey("lines"); + // End File. + emitDictEnd(); +} - // Start Line Coverage Summary. - emitDictStart(); - emitDictElement("count", Summary.LineCoverage.getNumLines()); - emitDictElement("covered", Summary.LineCoverage.getCovered()); - emitDictElement("percent", Summary.LineCoverage.getPercentCovered()); - // End Line Coverage Summary. - emitDictEnd(); +void CoverageExporterJson::renderSegment( + const coverage::CoverageSegment &Segment) { + // Start Segment. + emitArrayStart(); + + emitArrayElement(Segment.Line); + emitArrayElement(Segment.Col); + emitArrayElement(Segment.Count); + emitArrayElement(Segment.HasCount); + emitArrayElement(Segment.IsRegionEntry); - emitDictKey("functions"); + // End Segment. + emitArrayEnd(); +} - // Start Function Coverage Summary. - emitDictStart(); - emitDictElement("count", Summary.FunctionCoverage.getNumFunctions()); - emitDictElement("covered", Summary.FunctionCoverage.getExecuted()); - emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered()); - // End Function Coverage Summary. - emitDictEnd(); +void CoverageExporterJson::renderExpansion( + const coverage::ExpansionRecord &Expansion) { + // Start Expansion. + emitDictStart(); + + // Mark the beginning and end of this expansion in the source file. + emitDictKey("source_region"); + renderRegion(Expansion.Region); + + // Enumerate the coverage information for the expansion. + emitDictKey("target_regions"); + renderRegions(Expansion.Function.CountedRegions); + + emitDictKey("filenames"); + // Start List of Filenames to map the fileIDs. + emitArrayStart(); + for (const auto &Filename : Expansion.Function.Filenames) + emitArrayElement(Filename); + // End List of Filenames. + emitArrayEnd(); - emitDictKey("instantiations"); + // End Expansion. + emitDictEnd(); +} - // Start Instantiation Coverage Summary. - emitDictStart(); - emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions()); - emitDictElement("covered", Summary.InstantiationCoverage.getExecuted()); - emitDictElement("percent", - Summary.InstantiationCoverage.getPercentCovered()); - // End Function Coverage Summary. - emitDictEnd(); +void CoverageExporterJson::renderRegions( + ArrayRef Regions) { + // Start List of Regions. + emitArrayStart(); - emitDictKey("regions"); + for (const auto &Region : Regions) + renderRegion(Region); - // Start Region Coverage Summary. - emitDictStart(); - emitDictElement("count", Summary.RegionCoverage.getNumRegions()); - emitDictElement("covered", Summary.RegionCoverage.getCovered()); - emitDictElement("notcovered", - Summary.RegionCoverage.getNumRegions() - - Summary.RegionCoverage.getCovered()); - emitDictElement("percent", Summary.RegionCoverage.getPercentCovered()); - // End Region Coverage Summary. - emitDictEnd(); + // End List of Regions. + emitArrayEnd(); +} - // End Summary for the file. - emitDictEnd(); - } +void CoverageExporterJson::renderRegion(const coverage::CountedRegion &Region) { + // Start CountedRegion. + emitArrayStart(); + + emitArrayElement(Region.LineStart); + emitArrayElement(Region.ColumnStart); + emitArrayElement(Region.LineEnd); + emitArrayElement(Region.ColumnEnd); + emitArrayElement(Region.ExecutionCount); + emitArrayElement(Region.FileID); + emitArrayElement(Region.ExpandedFileID); + emitArrayElement(Region.Kind); -public: - CoverageExporterJson(const CoverageMapping &CoverageMapping, - const CoverageViewOptions &Options, raw_ostream &OS) - : Options(Options), OS(OS), Coverage(CoverageMapping) { - State.push(JsonState::None); - } + // End CountedRegion. + emitArrayEnd(); +} - /// \brief Print the CoverageMapping. - void print() { renderRoot(); } -}; - -/// \brief Export the given CoverageMapping to a JSON Format. -void exportCoverageDataToJson(const CoverageMapping &CoverageMapping, - const CoverageViewOptions &Options, - raw_ostream &OS) { - auto Exporter = CoverageExporterJson(CoverageMapping, Options, OS); +void CoverageExporterJson::renderSummary(const FileCoverageSummary &Summary) { + // Start Summary for the file. + emitDictStart(); + + emitDictKey("lines"); + + // Start Line Coverage Summary. + emitDictStart(); + emitDictElement("count", Summary.LineCoverage.getNumLines()); + emitDictElement("covered", Summary.LineCoverage.getCovered()); + emitDictElement("percent", Summary.LineCoverage.getPercentCovered()); + // End Line Coverage Summary. + emitDictEnd(); + + emitDictKey("functions"); + + // Start Function Coverage Summary. + emitDictStart(); + emitDictElement("count", Summary.FunctionCoverage.getNumFunctions()); + emitDictElement("covered", Summary.FunctionCoverage.getExecuted()); + emitDictElement("percent", Summary.FunctionCoverage.getPercentCovered()); + // End Function Coverage Summary. + emitDictEnd(); + + emitDictKey("instantiations"); + + // Start Instantiation Coverage Summary. + emitDictStart(); + emitDictElement("count", Summary.InstantiationCoverage.getNumFunctions()); + emitDictElement("covered", Summary.InstantiationCoverage.getExecuted()); + emitDictElement("percent", Summary.InstantiationCoverage.getPercentCovered()); + // End Function Coverage Summary. + emitDictEnd(); + + emitDictKey("regions"); + + // Start Region Coverage Summary. + emitDictStart(); + emitDictElement("count", Summary.RegionCoverage.getNumRegions()); + emitDictElement("covered", Summary.RegionCoverage.getCovered()); + emitDictElement("notcovered", Summary.RegionCoverage.getNumRegions() - + Summary.RegionCoverage.getCovered()); + emitDictElement("percent", Summary.RegionCoverage.getPercentCovered()); + // End Region Coverage Summary. + emitDictEnd(); - Exporter.print(); + // End Summary for the file. + emitDictEnd(); } Index: tools/llvm-cov/CoverageReport.h =================================================================== --- tools/llvm-cov/CoverageReport.h +++ tools/llvm-cov/CoverageReport.h @@ -1,4 +1,4 @@ -//===- CoverageReport.h - Code coverage report ---------------------------===// +//===- CoverageReport.h - Code coverage report ----------------------------===// // // The LLVM Compiler Infrastructure //