Mercurial > hg > CbC > CbC_llvm
comparison tools/llvm-cov/SourceCoverageView.cpp @ 121:803732b1fca8
LLVM 5.0
author | kono |
---|---|
date | Fri, 27 Oct 2017 17:07:41 +0900 |
parents | 1172e4bd9c6f |
children | 3a76565eade5 |
comparison
equal
deleted
inserted
replaced
120:1172e4bd9c6f | 121:803732b1fca8 |
---|---|
82 } | 82 } |
83 llvm_unreachable("Unknown coverage output format!"); | 83 llvm_unreachable("Unknown coverage output format!"); |
84 } | 84 } |
85 | 85 |
86 unsigned SourceCoverageView::getFirstUncoveredLineNo() { | 86 unsigned SourceCoverageView::getFirstUncoveredLineNo() { |
87 auto CheckIfUncovered = [](const coverage::CoverageSegment &S) { | 87 const auto MinSegIt = find_if(CoverageInfo, [](const CoverageSegment &S) { |
88 return S.HasCount && S.Count == 0; | 88 return S.HasCount && S.Count == 0; |
89 }; | 89 }); |
90 // L is less than R if (1) it's an uncovered segment (has a 0 count), and (2) | 90 |
91 // either R is not an uncovered segment, or L has a lower line number than R. | |
92 const auto MinSegIt = | |
93 std::min_element(CoverageInfo.begin(), CoverageInfo.end(), | |
94 [CheckIfUncovered](const coverage::CoverageSegment &L, | |
95 const coverage::CoverageSegment &R) { | |
96 return (CheckIfUncovered(L) && | |
97 (!CheckIfUncovered(R) || (L.Line < R.Line))); | |
98 }); | |
99 if (CheckIfUncovered(*MinSegIt)) | |
100 return (*MinSegIt).Line; | |
101 // There is no uncovered line, return zero. | 91 // There is no uncovered line, return zero. |
102 return 0; | 92 if (MinSegIt == CoverageInfo.end()) |
93 return 0; | |
94 | |
95 return (*MinSegIt).Line; | |
103 } | 96 } |
104 | 97 |
105 std::string SourceCoverageView::formatCount(uint64_t N) { | 98 std::string SourceCoverageView::formatCount(uint64_t N) { |
106 std::string Number = utostr(N); | 99 std::string Number = utostr(N); |
107 int Len = Number.size(); | 100 int Len = Number.size(); |
116 Result.push_back(" kMGTPEZY"[(Len - 1) / 3]); | 109 Result.push_back(" kMGTPEZY"[(Len - 1) / 3]); |
117 return Result; | 110 return Result; |
118 } | 111 } |
119 | 112 |
120 bool SourceCoverageView::shouldRenderRegionMarkers( | 113 bool SourceCoverageView::shouldRenderRegionMarkers( |
121 bool LineHasMultipleRegions) const { | 114 CoverageSegmentArray Segments) const { |
122 return getOptions().ShowRegionMarkers && | 115 if (!getOptions().ShowRegionMarkers) |
123 (!getOptions().ShowLineStatsOrRegionMarkers || LineHasMultipleRegions); | 116 return false; |
117 | |
118 // Render the region markers if there's more than one count to show. | |
119 unsigned RegionCount = 0; | |
120 for (const auto *S : Segments) | |
121 if (S->IsRegionEntry) | |
122 if (++RegionCount > 1) | |
123 return true; | |
124 return false; | |
124 } | 125 } |
125 | 126 |
126 bool SourceCoverageView::hasSubViews() const { | 127 bool SourceCoverageView::hasSubViews() const { |
127 return !ExpansionSubViews.empty() || !InstantiationSubViews.empty(); | 128 return !ExpansionSubViews.empty() || !InstantiationSubViews.empty(); |
128 } | 129 } |
129 | 130 |
130 std::unique_ptr<SourceCoverageView> | 131 std::unique_ptr<SourceCoverageView> |
131 SourceCoverageView::create(StringRef SourceName, const MemoryBuffer &File, | 132 SourceCoverageView::create(StringRef SourceName, const MemoryBuffer &File, |
132 const CoverageViewOptions &Options, | 133 const CoverageViewOptions &Options, |
133 coverage::CoverageData &&CoverageInfo) { | 134 CoverageData &&CoverageInfo) { |
134 switch (Options.Format) { | 135 switch (Options.Format) { |
135 case CoverageViewOptions::OutputFormat::Text: | 136 case CoverageViewOptions::OutputFormat::Text: |
136 return llvm::make_unique<SourceCoverageViewText>( | 137 return llvm::make_unique<SourceCoverageViewText>( |
137 SourceName, File, Options, std::move(CoverageInfo)); | 138 SourceName, File, Options, std::move(CoverageInfo)); |
138 case CoverageViewOptions::OutputFormat::HTML: | 139 case CoverageViewOptions::OutputFormat::HTML: |
148 sys::path::native(SourceText); | 149 sys::path::native(SourceText); |
149 return SourceText.str(); | 150 return SourceText.str(); |
150 } | 151 } |
151 | 152 |
152 void SourceCoverageView::addExpansion( | 153 void SourceCoverageView::addExpansion( |
153 const coverage::CounterMappingRegion &Region, | 154 const CounterMappingRegion &Region, |
154 std::unique_ptr<SourceCoverageView> View) { | 155 std::unique_ptr<SourceCoverageView> View) { |
155 ExpansionSubViews.emplace_back(Region, std::move(View)); | 156 ExpansionSubViews.emplace_back(Region, std::move(View)); |
156 } | 157 } |
157 | 158 |
158 void SourceCoverageView::addInstantiation( | 159 void SourceCoverageView::addInstantiation( |
160 std::unique_ptr<SourceCoverageView> View) { | 161 std::unique_ptr<SourceCoverageView> View) { |
161 InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View)); | 162 InstantiationSubViews.emplace_back(FunctionName, Line, std::move(View)); |
162 } | 163 } |
163 | 164 |
164 void SourceCoverageView::print(raw_ostream &OS, bool WholeFile, | 165 void SourceCoverageView::print(raw_ostream &OS, bool WholeFile, |
165 bool ShowSourceName, unsigned ViewDepth) { | 166 bool ShowSourceName, bool ShowTitle, |
166 if (WholeFile && getOptions().hasOutputDirectory()) | 167 unsigned ViewDepth) { |
168 if (ShowTitle) | |
167 renderTitle(OS, "Coverage Report"); | 169 renderTitle(OS, "Coverage Report"); |
168 | 170 |
169 renderViewHeader(OS); | 171 renderViewHeader(OS); |
170 | 172 |
171 if (ShowSourceName) | 173 if (ShowSourceName) |
174 renderTableHeader(OS, (ViewDepth > 0) ? 0 : getFirstUncoveredLineNo(), | 176 renderTableHeader(OS, (ViewDepth > 0) ? 0 : getFirstUncoveredLineNo(), |
175 ViewDepth); | 177 ViewDepth); |
176 | 178 |
177 // We need the expansions and instantiations sorted so we can go through them | 179 // We need the expansions and instantiations sorted so we can go through them |
178 // while we iterate lines. | 180 // while we iterate lines. |
179 std::sort(ExpansionSubViews.begin(), ExpansionSubViews.end()); | 181 std::stable_sort(ExpansionSubViews.begin(), ExpansionSubViews.end()); |
180 std::sort(InstantiationSubViews.begin(), InstantiationSubViews.end()); | 182 std::stable_sort(InstantiationSubViews.begin(), InstantiationSubViews.end()); |
181 auto NextESV = ExpansionSubViews.begin(); | 183 auto NextESV = ExpansionSubViews.begin(); |
182 auto EndESV = ExpansionSubViews.end(); | 184 auto EndESV = ExpansionSubViews.end(); |
183 auto NextISV = InstantiationSubViews.begin(); | 185 auto NextISV = InstantiationSubViews.begin(); |
184 auto EndISV = InstantiationSubViews.end(); | 186 auto EndISV = InstantiationSubViews.end(); |
185 | 187 |
186 // Get the coverage information for the file. | 188 // Get the coverage information for the file. |
187 auto NextSegment = CoverageInfo.begin(); | 189 auto StartSegment = CoverageInfo.begin(); |
188 auto EndSegment = CoverageInfo.end(); | 190 auto EndSegment = CoverageInfo.end(); |
189 | 191 LineCoverageIterator LCI{CoverageInfo, 1}; |
190 unsigned FirstLine = NextSegment != EndSegment ? NextSegment->Line : 0; | 192 LineCoverageIterator LCIEnd = LCI.getEnd(); |
191 const coverage::CoverageSegment *WrappedSegment = nullptr; | 193 |
192 SmallVector<const coverage::CoverageSegment *, 8> LineSegments; | 194 unsigned FirstLine = StartSegment != EndSegment ? StartSegment->Line : 0; |
193 for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI) { | 195 for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); |
196 ++LI, ++LCI) { | |
194 // If we aren't rendering the whole file, we need to filter out the prologue | 197 // If we aren't rendering the whole file, we need to filter out the prologue |
195 // and epilogue. | 198 // and epilogue. |
196 if (!WholeFile) { | 199 if (!WholeFile) { |
197 if (NextSegment == EndSegment) | 200 if (LCI == LCIEnd) |
198 break; | 201 break; |
199 else if (LI.line_number() < FirstLine) | 202 else if (LI.line_number() < FirstLine) |
200 continue; | 203 continue; |
201 } | 204 } |
202 | 205 |
203 // Collect the coverage information relevant to this line. | |
204 if (LineSegments.size()) | |
205 WrappedSegment = LineSegments.back(); | |
206 LineSegments.clear(); | |
207 while (NextSegment != EndSegment && NextSegment->Line == LI.line_number()) | |
208 LineSegments.push_back(&*NextSegment++); | |
209 | |
210 // Calculate a count to be for the line as a whole. | |
211 LineCoverageStats LineCount; | |
212 if (WrappedSegment && WrappedSegment->HasCount) | |
213 LineCount.addRegionCount(WrappedSegment->Count); | |
214 for (const auto *S : LineSegments) | |
215 if (S->HasCount && S->IsRegionEntry) | |
216 LineCount.addRegionStartCount(S->Count); | |
217 | |
218 renderLinePrefix(OS, ViewDepth); | 206 renderLinePrefix(OS, ViewDepth); |
219 if (getOptions().ShowLineNumbers) | 207 if (getOptions().ShowLineNumbers) |
220 renderLineNumberColumn(OS, LI.line_number()); | 208 renderLineNumberColumn(OS, LI.line_number()); |
209 | |
221 if (getOptions().ShowLineStats) | 210 if (getOptions().ShowLineStats) |
222 renderLineCoverageColumn(OS, LineCount); | 211 renderLineCoverageColumn(OS, *LCI); |
223 | 212 |
224 // If there are expansion subviews, we want to highlight the first one. | 213 // If there are expansion subviews, we want to highlight the first one. |
225 unsigned ExpansionColumn = 0; | 214 unsigned ExpansionColumn = 0; |
226 if (NextESV != EndESV && NextESV->getLine() == LI.line_number() && | 215 if (NextESV != EndESV && NextESV->getLine() == LI.line_number() && |
227 getOptions().Colors) | 216 getOptions().Colors) |
228 ExpansionColumn = NextESV->getStartCol(); | 217 ExpansionColumn = NextESV->getStartCol(); |
229 | 218 |
230 // Display the source code for the current line. | 219 // Display the source code for the current line. |
231 renderLine(OS, {*LI, LI.line_number()}, WrappedSegment, LineSegments, | 220 renderLine(OS, {*LI, LI.line_number()}, *LCI, ExpansionColumn, ViewDepth); |
232 ExpansionColumn, ViewDepth); | |
233 | 221 |
234 // Show the region markers. | 222 // Show the region markers. |
235 if (shouldRenderRegionMarkers(LineCount.hasMultipleRegions())) | 223 if (shouldRenderRegionMarkers(LCI->getLineSegments())) |
236 renderRegionMarkers(OS, LineSegments, ViewDepth); | 224 renderRegionMarkers(OS, *LCI, ViewDepth); |
237 | 225 |
238 // Show the expansions and instantiations for this line. | 226 // Show the expansions and instantiations for this line. |
239 bool RenderedSubView = false; | 227 bool RenderedSubView = false; |
240 for (; NextESV != EndESV && NextESV->getLine() == LI.line_number(); | 228 for (; NextESV != EndESV && NextESV->getLine() == LI.line_number(); |
241 ++NextESV) { | 229 ++NextESV) { |
243 | 231 |
244 // Re-render the current line and highlight the expansion range for | 232 // Re-render the current line and highlight the expansion range for |
245 // this subview. | 233 // this subview. |
246 if (RenderedSubView) { | 234 if (RenderedSubView) { |
247 ExpansionColumn = NextESV->getStartCol(); | 235 ExpansionColumn = NextESV->getStartCol(); |
248 renderExpansionSite(OS, {*LI, LI.line_number()}, WrappedSegment, | 236 renderExpansionSite(OS, {*LI, LI.line_number()}, *LCI, ExpansionColumn, |
249 LineSegments, ExpansionColumn, ViewDepth); | 237 ViewDepth); |
250 renderViewDivider(OS, ViewDepth + 1); | 238 renderViewDivider(OS, ViewDepth + 1); |
251 } | 239 } |
252 | 240 |
253 renderExpansionView(OS, *NextESV, ViewDepth + 1); | 241 renderExpansionView(OS, *NextESV, ViewDepth + 1); |
254 RenderedSubView = true; | 242 RenderedSubView = true; |