rubberduck-vba / Rubberduck

@@ -80,7 +80,7 @@
Loading
80 80
            INavigateCommand navigateCommand, 
81 81
            ReparseCommand reparseCommand,
82 82
            IClipboardWriter clipboard,
83 -
            IConfigurationService<Configuration> configService, 
83 +
            IConfigurationService<Configuration> configService,
84 84
            ISettingsFormFactory settingsFormFactory,
85 85
            IUiDispatcher uiDispatcher)
86 86
        {
@@ -96,8 +96,8 @@
Loading
96 96
            RefreshCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(),
97 97
                o =>
98 98
                {
99 -
                    IsRefreshing = true;
100 99
                    IsBusy = true;
100 +
                    _forceRefreshResults = true;
101 101
                    var cancellation = new ReparseCancellationFlag();
102 102
                    reparseCommand.Execute(cancellation);
103 103
                    if (cancellation.Canceled)
@@ -136,11 +136,6 @@
Loading
136 136
            _state.StateChanged += HandleStateChanged;
137 137
        }
138 138
139 -
        /// <summary>
140 -
        /// Gets/sets a flag indicating whether the parser state changes are a result of our RefreshCommand.
141 -
        /// </summary>
142 -
        private bool IsRefreshing { get; set; }
143 -
144 139
        private void _configService_SettingsChanged(object sender, ConfigurationChangedEventArgs e)
145 140
        {            
146 141
            if (e.InspectionSettingsChanged)
@@ -235,9 +230,12 @@
Loading
235 230
                }
236 231
237 232
                _grouping = value;
238 -
                Results.GroupDescriptions.Clear();
239 -
                Results.GroupDescriptions.Add(GroupDescriptions[_grouping]);
240 -
                Results.Refresh();
233 +
                // Deferring refresh to avoid a rerendering without grouping
234 +
                using (Results.DeferRefresh())
235 +
                {
236 +
                    Results.GroupDescriptions.Clear();
237 +
                    Results.GroupDescriptions.Add(GroupDescriptions[_grouping]);
238 +
                }
241 239
                OnPropertyChanged();
242 240
            }
243 241
        }
@@ -255,7 +253,9 @@
Loading
255 253
256 254
                _filters = value;
257 255
                OnPropertyChanged();
258 -
                Results.Refresh();
256 +
257 +
                // updating Filter forces a Refresh
258 +
                Results.Filter = i => InspectionFilter((IInspectionResult)i);
259 259
            }
260 260
        }
261 261
@@ -311,7 +311,6 @@
Loading
311 311
        }
312 312
313 313
        private bool _canQuickFix;
314 -
315 314
        public bool CanQuickFix
316 315
        {
317 316
            get => _canQuickFix;
@@ -333,6 +332,12 @@
Loading
333 332
            } 
334 333
        }
335 334
335 +
        /// <summary>
336 +
        /// A boolean indicating that a local refresh was triggered.
337 +
        /// When this is set to true, InspectionResults are refreshed, even when inspecting after successful parsing is disabled.
338 +
        /// </summary>
339 +
        private bool _forceRefreshResults = false;
340 +
336 341
        private bool _unparsed = true;
337 342
        public bool Unparsed
338 343
        {
@@ -362,14 +367,17 @@
Loading
362 367
        private bool _runInspectionsOnReparse;
363 368
        private void HandleStateChanged(object sender, ParserStateEventArgs e)
364 369
        {
365 -
            if (!IsRefreshing && (_state.Status == ParserState.Pending || _state.Status == ParserState.Error || _state.Status == ParserState.ResolverError))
370 +
            if (_state.Status == ParserState.Pending || _state.Status == ParserState.Error || _state.Status == ParserState.ResolverError)
366 371
            {
372 +
                // an error in parser state resets the busy state
367 373
                IsBusy = false;
368 374
                return;
369 375
            }
370 376
371 377
            if(_state.Status != ParserState.Ready)
372 378
            {
379 +
                // not an error, but also not finished -> We're busy
380 +
                IsBusy = true;
373 381
                return;
374 382
            }
375 383
@@ -378,7 +386,9 @@
Loading
378 386
                return;
379 387
            }
380 388
381 -
            if (_runInspectionsOnReparse || IsRefreshing)
389 +
            // push Unparsed to false on the first successful parse
390 +
            Unparsed = false;
391 +
            if (_runInspectionsOnReparse || _forceRefreshResults)
382 392
            {
383 393
                RefreshInspections(e.Token);
384 394
            }
@@ -388,6 +398,7 @@
Loading
388 398
                var modifiedModules = _state.DeclarationFinder.AllModules.ToHashSet();
389 399
                InvalidateStaleInspectionResults(modifiedModules);
390 400
            }
401 +
            IsBusy = false;
391 402
        }
392 403
393 404
        private async void RefreshInspections(CancellationToken token)
@@ -409,9 +420,7 @@
Loading
409 420
            }
410 421
411 422
            stopwatch.Stop();
412 -
            LogManager.GetCurrentClassLogger().Trace("Inspection results returned in {0}ms", stopwatch.ElapsedMilliseconds);
413 -
414 -
            Unparsed = false;
423 +
            Logger.Trace("Inspection results returned in {0}ms", stopwatch.ElapsedMilliseconds);
415 424
416 425
            _uiDispatcher.Invoke(() =>
417 426
            {
@@ -423,28 +432,27 @@
Loading
423 432
                    {
424 433
                        _results.Add(result);
425 434
                    }
426 -
427 435
                    Results.Refresh();
428 -
                    SelectedItem = null;
429 436
                }
430 437
                catch (Exception exception)
431 438
                {
432 -
                    Logger.Error(exception, "Exception thrown trying to refresh the inspection results view on th UI thread.");
439 +
                    Logger.Error(exception, "Exception thrown trying to refresh the inspection results view on the UI thread.");
433 440
                }
434 441
                finally
435 442
                {
436 443
                    IsBusy = false;
437 -
                    IsRefreshing = false;
444 +
                    // refreshing results is only disabled when successful
445 +
                    // It's basically a "refresh on success once".
446 +
                    _forceRefreshResults = false;
438 447
                }
439 448
440 449
                stopwatch.Stop();
441 -
                LogManager.GetCurrentClassLogger().Trace("Inspection results rendered in {0}ms", stopwatch.ElapsedMilliseconds);
450 +
                Logger.Trace("Inspection results rendered in {0}ms", stopwatch.ElapsedMilliseconds);
442 451
            });
443 452
        }
444 453
445 -
        private void InvalidateStaleInspectionResults(ICollection<QualifiedModuleName> modifiedModules)
454 +
        private void InvalidateUIStaleInspectionResults(ICollection<IInspectionResult> staleResults)
446 455
        {
447 -
            var staleResults = _results.Where(result => result.ChangesInvalidateResult(modifiedModules)).ToList();
448 456
            _uiDispatcher.Invoke(() =>
449 457
            {
450 458
                foreach (var staleResult in staleResults)
@@ -455,6 +463,13 @@
Loading
455 463
            });
456 464
        }
457 465
466 +
        private void InvalidateStaleInspectionResults(ICollection<QualifiedModuleName> modifiedModules)
467 +
        {
468 +
            // materialize the collection to take work off of the UI thread
469 +
            var staleResults = _results.Where(result => result.ChangesInvalidateResult(modifiedModules)).ToList();
470 +
            InvalidateUIStaleInspectionResults(staleResults);
471 +
        }
472 +
458 473
        private void ExecuteQuickFixCommand(object parameter)
459 474
        {
460 475
            var quickFix = parameter as IQuickFix;
@@ -547,14 +562,12 @@
Loading
547 562
548 563
            Task.Run(() => _configService.Save(config));
549 564
550 -
            _uiDispatcher.Invoke(() =>
551 -
            {
552 -
                RefreshCommand.Execute(null);
553 -
            });
565 +
            // remove inspection results of the selected inspection from the UI
566 +
            // collection is materialized to take work off of the UI thread
567 +
            InvalidateUIStaleInspectionResults(_results.Where(i => i.Inspection == _selectedInspection).ToList());
554 568
        }
555 569
556 570
        private bool _canDisableInspection;
557 -
558 571
        public bool CanDisableInspection
559 572
        {
560 573
            get => _canDisableInspection;

@@ -17,7 +17,7 @@
Loading
17 17
            <ResourceDictionary.MergedDictionaries>
18 18
                <ResourceDictionary Source="../Controls/ToolBar.xaml"/>
19 19
            </ResourceDictionary.MergedDictionaries>
20 -
20 +
            
21 21
            <codeInspections:InspectionSeverityImageSourceConverter x:Key="SeverityIconConverter" />
22 22
            <codeInspections:InspectionImageSourceConverter x:Key="InspectionIconConverter" />
23 23
            <codeInspections:QuickFixImageSourceConverter x:Key="QuickFixIconConverter" />
@@ -26,24 +26,6 @@
Loading
26 26
                <Setter Property="Margin" Value="4" />
27 27
            </Style>
28 28
29 -
            <BitmapImage x:Key="CopyResultsImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/document-copy.png" />
30 -
            <BitmapImage x:Key="SettingsImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/gear.png" />
31 -
            <BitmapImage x:Key="RefreshImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/arrow-circle-double.png" />
32 -
            <BitmapImage x:Key="FixImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/tick.png" />
33 -
34 -
            <BitmapImage x:Key="GroupByInspectionTypeImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/block.png" />
35 -
            <BitmapImage x:Key="GroupByInspectionImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/light-bulb-code.png" />
36 -
            <BitmapImage x:Key="GroupByLocationImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Custom/PNG/ObjectClass.png" />
37 -
            <BitmapImage x:Key="GroupBySeverityImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Custom/PNG/Severity.png" />
38 -
39 -
            <BitmapImage x:Key="FilterByHintImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/information-white.png" />
40 -
            <BitmapImage x:Key="FilterBySuggestionImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/information.png" />
41 -
            <BitmapImage x:Key="FilterByWarningImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/exclamation.png" />
42 -
            <BitmapImage x:Key="FilterByErrorImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/cross-circle.png" />
43 -
44 -
            <BitmapImage x:Key="ExpandAllImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/expand-all.png" />
45 -
            <BitmapImage x:Key="CollapseAllImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/collapse-all.png" />
46 -
47 29
            <Style TargetType="Image">
48 30
                <Setter Property="Height" Value="16"/>
49 31
                <Setter Property="Width" Value="16" />
@@ -63,18 +45,29 @@
Loading
63 45
64 46
            <ToolBar Style="{StaticResource ToolBarWithOverflowOnlyShowingWhenNeededStyle}">
65 47
                <ToolBar.Resources>
66 -
                    <codeInspections:InspectionFilterToBooleanConverter x:Key="ErrorFlagConverter" />
67 -
                    <codeInspections:InspectionFilterToBooleanConverter x:Key="WarningFlagConverter" />
68 -
                    <codeInspections:InspectionFilterToBooleanConverter x:Key="SuggestionFlagConverter" />
69 -
                    <codeInspections:InspectionFilterToBooleanConverter x:Key="HintFlagConverter" />
70 -
                    <codeInspections:InspectionResultGroupingToBooleanConverter x:Key="GroupByTypeConverter" />
71 -
                    <codeInspections:InspectionResultGroupingToBooleanConverter x:Key="GroupByNameConverter" />
72 -
                    <codeInspections:InspectionResultGroupingToBooleanConverter x:Key="GroupByLocationConverter" />
73 -
                    <codeInspections:InspectionResultGroupingToBooleanConverter x:Key="GroupBySeverityConverter" />
48 +
                    <codeInspections:InspectionFilterToBooleanConverter x:Key="InspectionTypeToBooleanConverter" />
49 +
                    <codeInspections:InspectionResultGroupingToBooleanConverter x:Key="GroupingToBooleanConverter" />
74 50
                    <Style x:Key="ToolBarToggleStyle" TargetType="ToggleButton">
75 51
                        <Setter Property="Margin" Value="2" />
76 52
                        <Setter Property="BorderBrush" Value="{x:Static SystemColors.ActiveBorderBrush}" />
77 53
                    </Style>
54 +
                    <BitmapImage x:Key="CopyResultsImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/document-copy.png" />
55 +
                    <BitmapImage x:Key="SettingsImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/gear.png" />
56 +
                    <BitmapImage x:Key="RefreshImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/arrow-circle-double.png" />
57 +
                    <BitmapImage x:Key="FixImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/tick.png" />
58 +
59 +
                    <BitmapImage x:Key="GroupByInspectionTypeImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/block.png" />
60 +
                    <BitmapImage x:Key="GroupByInspectionImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/light-bulb-code.png" />
61 +
                    <BitmapImage x:Key="GroupByLocationImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Custom/PNG/ObjectClass.png" />
62 +
                    <BitmapImage x:Key="GroupBySeverityImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Custom/PNG/Severity.png" />
63 +
64 +
                    <BitmapImage x:Key="FilterByHintImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/information-white.png" />
65 +
                    <BitmapImage x:Key="FilterBySuggestionImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/information.png" />
66 +
                    <BitmapImage x:Key="FilterByWarningImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/exclamation.png" />
67 +
                    <BitmapImage x:Key="FilterByErrorImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/cross-circle.png" />
68 +
69 +
                    <BitmapImage x:Key="ExpandAllImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/expand-all.png" />
70 +
                    <BitmapImage x:Key="CollapseAllImage" UriSource="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/collapse-all.png" />
78 71
                </ToolBar.Resources>
79 72
80 73
                <Button Command="{Binding RefreshCommand}">
@@ -114,25 +107,25 @@
Loading
114 107
115 108
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
116 109
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingStyle_ByInspectionType}"
117 -
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupByTypeConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Type}}">
110 +
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupingToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Type}}">
118 111
                    <Image Source="{StaticResource GroupByInspectionTypeImage}" />
119 112
                </ToggleButton>
120 113
121 114
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
122 115
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingStyle_ByName}"
123 -
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupByNameConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Name}}">
116 +
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupingToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Name}}">
124 117
                    <Image Source="{StaticResource GroupByInspectionImage}" />
125 118
                </ToggleButton>
126 119
127 120
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
128 121
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingStyle_ByLocation}"
129 -
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupByLocationConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Location}}">
122 +
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupingToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Location}}">
130 123
                    <Image Source="{StaticResource GroupByLocationImage}" />
131 124
                </ToggleButton>
132 125
133 126
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
134 127
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingStyle_BySeverity}"
135 -
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupBySeverityConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Severity}}">
128 +
                              IsChecked="{Binding Path=Grouping, Converter={StaticResource GroupingToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultGrouping.Severity}}">
136 129
                    <Image Source="{StaticResource GroupBySeverityImage}" />
137 130
                </ToggleButton>
138 131
@@ -142,25 +135,25 @@
Loading
142 135
143 136
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
144 137
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterByError}"
145 -
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource ErrorFlagConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Error}}">
138 +
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource InspectionTypeToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Error}}">
146 139
                    <Image Source="{StaticResource FilterByErrorImage}" />
147 140
                </ToggleButton>
148 141
149 142
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
150 143
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterByWarning}"
151 -
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource WarningFlagConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Warning}}">
144 +
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource InspectionTypeToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Warning}}">
152 145
                    <Image Source="{StaticResource FilterByWarningImage}" />
153 146
                </ToggleButton>
154 147
155 148
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
156 149
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterBySuggestion}"
157 -
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource SuggestionFlagConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Suggestion}}">
150 +
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource InspectionTypeToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Suggestion}}">
158 151
                    <Image Source="{StaticResource FilterBySuggestionImage}" />
159 152
                </ToggleButton>
160 153
161 154
                <ToggleButton Style="{StaticResource ToolBarToggleStyle}"
162 155
                              ToolTip="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=InspectionResults_FilterByHint}"
163 -
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource HintFlagConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Hint}}">
156 +
                              IsChecked="{Binding Path=SelectedFilters, Converter={StaticResource InspectionTypeToBooleanConverter}, ConverterParameter={x:Static codeInspections:InspectionResultsFilter.Hint}}">
164 157
                    <Image Source="{StaticResource FilterByHintImage}" />
165 158
                </ToggleButton>
166 159
@@ -199,7 +192,7 @@
Loading
199 192
                               SelectedItem="{Binding SelectedItem}"
200 193
                               SelectionUnit="FullRow"
201 194
                               ItemsSource="{Binding Results, NotifyOnSourceUpdated=True}"
202 -
                               VirtualizingPanel.IsVirtualizingWhenGrouping="False">
195 +
                               VirtualizingPanel.IsVirtualizingWhenGrouping="True">
203 196
            <DataGrid.RowDetailsTemplate>
204 197
                <DataTemplate>
205 198
                    <Grid>
@@ -242,8 +235,6 @@
Loading
242 235
        </controls:GroupingGrid>
243 236
244 237
        <controls:EmptyUIRefresh Grid.Row="1" Visibility="{Binding Unparsed, Converter={StaticResource BoolToVisibility}}" />
245 -
246 -
247 238
        <controls:BusyIndicator Grid.Row="1" Width="120" Height="120" Visibility="{Binding IsBusy, Converter={StaticResource BoolToVisibility}}" />
248 239
249 240
        <GridSplitter Grid.Row="2" Height="5" ShowsPreview="True" Cursor="SizeNS" HorizontalAlignment="Stretch"/>
Files Coverage
Rubberduck.CodeAnalysis 88.85%
Rubberduck.Core 32.02%
Rubberduck.Interaction 9.80%
Rubberduck.Main 46.71%
Rubberduck.Parsing 80.37%
Rubberduck.Refactorings 89.20%
Rubberduck.RegexAssistant 65.19%
Rubberduck.Resources 66.67%
Rubberduck.SettingsProvider 31.72%
Rubberduck.SmartIndenter 78.72%
Rubberduck.UnitTesting 68.22%
RubberduckCodeAnalysis 60.62%
Rubberduck.JunkDrawer/Output/StringExtensions.cs 87.50%
Project Totals (1079 files) 64.23%
tukxk3lafxm263b4
1
codecov:
2
  branch: next
3
  ci:
4
    - appveyor
5
  max_report_age: off
6
  
7
ignore:
8
  # as requested by MDoerner, because they aren't really testable
9
  - Rubberduck.VBEEditor
10
  - Rubberduck.VBEditor.*
11
  # it makes no sense to track coverage on unit-tests
12
  - RubberduckTests
13
  # xaml files are not checked for coverage
14
  # AutoGenerated files are not contributing to coverage
15
  - **/*.Designer.cs
16
    
17
coverage:
18
  round: nearest
19
  precision: 2
20
  range: 40..80 
21
  status:
22
    # don't check patch coverage
23
    patch: off
24
    project:
25
      default:
26
        target: 0 # don't force a minimum coverage
27
        # allow decrease by up to 5 %
28
        threshold: 5
29
        base: auto
30
  
31
comment:
32
  layout: "flags, diff, files"
33
  behavior: once
34
  require_changes: yes
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading