Skip to content
This repository was archived by the owner on Jul 16, 2023. It is now read-only.

Commit 6ee7dea

Browse files
authored
feat: introduce summary report models (#496)
* chore: cleanup collect coverage workflow * feat: introduce summary report models * refactor: pass summary records to report * feat: introduce simple summary report * chore: update changelog * chore: fixes after review * chore: fixes after review * refactor: rename SummaryLintReportRecord.overflows to SummaryLintReportRecord.violations * chore: update tests * chore: fixes after review
1 parent 7ba5e66 commit 6ee7dea

File tree

26 files changed

+424
-40
lines changed

26 files changed

+424
-40
lines changed

.github/workflows/build.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ jobs:
3737
if: success()
3838
run: |
3939
dart test --coverage=coverage
40-
dart pub run coverage:format_coverage --packages=.packages -i coverage -o coverage/coverage.lcov --lcov --report-on=lib
40+
dart run coverage:format_coverage --packages=.packages -i coverage -o coverage/coverage.lcov --lcov --report-on=lib
4141
dart run tool/uncovered_coverage.dart
4242
dart test test/fake_test.dart --coverage=coverage
43-
dart pub run coverage:format_coverage --packages=.packages -i coverage -o coverage/coverage.lcov --lcov --report-on=lib
43+
dart run coverage:format_coverage --packages=.packages -i coverage -o coverage/coverage.lcov --lcov --report-on=lib
4444
bash <(curl -s https://codecov.io/bash) -f coverage/coverage.lcov
4545
4646
minimal-dart:

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
* feat: add static code diagnostics `prefer-correct-type-name`, `prefer-last`, `avoid-nested-conditional-expressions`.
6+
* feat: introduce summary report.
67
* chore: deprecate documentation in Github repo.
78
* chore: restrict `analyzer` version to `>=2.4.0 <2.7.0`.
89

lib/src/analyzers/lint_analyzer/lint_analyzer.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import '../../utils/file_utils.dart';
1212
import '../../utils/node_utils.dart';
1313
import 'lint_analysis_config.dart';
1414
import 'lint_config.dart';
15+
import 'metrics/metrics_list/cyclomatic_complexity/cyclomatic_complexity_metric.dart';
16+
import 'metrics/metrics_list/source_lines_of_code/source_lines_of_code_metric.dart';
1517
import 'metrics/models/metric_value.dart';
1618
import 'metrics/scope_visitor.dart';
1719
import 'models/internal_resolved_unit_result.dart';
@@ -20,8 +22,10 @@ import 'models/lint_file_report.dart';
2022
import 'models/report.dart';
2123
import 'models/scoped_class_declaration.dart';
2224
import 'models/scoped_function_declaration.dart';
25+
import 'models/summary_lint_report_record.dart';
2326
import 'models/suppression.dart';
2427
import 'reporters/reporter_factory.dart';
28+
import 'utils/report_utils.dart';
2529

2630
class LintAnalyzer {
2731
const LintAnalyzer();
@@ -112,6 +116,40 @@ class LintAnalyzer {
112116
return analyzerResult;
113117
}
114118

119+
Iterable<SummaryLintReportRecord> getSummary(
120+
Iterable<LintFileReport> records,
121+
) =>
122+
[
123+
SummaryLintReportRecord<Iterable<String>>(
124+
title: 'Scanned folders',
125+
value: scannedFolders(records),
126+
),
127+
SummaryLintReportRecord<int>(
128+
title: 'Total scanned files',
129+
value: totalFiles(records),
130+
),
131+
SummaryLintReportRecord<int>(
132+
title: 'Total lines of source code',
133+
value: totalSLOC(records),
134+
),
135+
SummaryLintReportRecord<int>(
136+
title: 'Total classes',
137+
value: totalClasses(records),
138+
),
139+
SummaryLintReportRecord<num>(
140+
title: 'Average Cyclomatic Number per line of code',
141+
value: averageCYCLO(records),
142+
violations:
143+
metricViolations(records, CyclomaticComplexityMetric.metricId),
144+
),
145+
SummaryLintReportRecord<int>(
146+
title: 'Average Source Lines of Code per method',
147+
value: averageSLOC(records),
148+
violations:
149+
metricViolations(records, SourceLinesOfCodeMetric.metricId),
150+
),
151+
];
152+
115153
LintFileReport? _analyzeFile(
116154
ResolvedUnitResult result,
117155
LintAnalysisConfig config,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import 'package:meta/meta.dart';
2+
3+
import 'summary_lint_report_record_status.dart';
4+
5+
@immutable
6+
class SummaryLintReportRecord<T> {
7+
final SummaryLintReportRecordStatus status;
8+
9+
final String title;
10+
11+
final T value;
12+
final T? violations;
13+
14+
const SummaryLintReportRecord({
15+
this.status = SummaryLintReportRecordStatus.none,
16+
required this.title,
17+
required this.value,
18+
this.violations,
19+
});
20+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/// Enum class represent of summary report.
2+
class SummaryLintReportRecordStatus {
3+
/// Error.
4+
///
5+
/// Status indicates that a record contains error information.
6+
/// Commonly represend by ❌ emoji
7+
static const error = SummaryLintReportRecordStatus._('error');
8+
9+
/// Warning.
10+
///
11+
/// Status indicates that a record requires user attention.
12+
/// Commonly represend by ⚠️ emoji.
13+
static const warning = SummaryLintReportRecordStatus._('warning');
14+
15+
/// OK.
16+
///
17+
/// Standard status for successful record.
18+
/// Commonly represend by ✅ emoji.
19+
static const ok = SummaryLintReportRecordStatus._('ok');
20+
21+
/// None.
22+
///
23+
/// Status for a record without a decision.
24+
static const none = SummaryLintReportRecordStatus._('none');
25+
26+
static const values = [error, warning, ok, none];
27+
28+
final String _value;
29+
30+
const SummaryLintReportRecordStatus._(this._value);
31+
32+
@override
33+
String toString() => _value;
34+
}

lib/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,25 @@ import '../../../models/issue.dart';
99
import '../../../models/lint_file_report.dart';
1010
import '../../../models/report.dart';
1111
import '../../../models/severity.dart';
12+
import '../../../models/summary_lint_report_record.dart';
1213
import 'models/code_climate_issue.dart';
1314
import 'models/code_climate_issue_category.dart';
1415
import 'models/code_climate_issue_location.dart';
1516
import 'models/code_climate_issue_severity.dart';
1617

17-
class LintCodeClimateReporter extends CodeClimateReporter<LintFileReport> {
18+
class LintCodeClimateReporter
19+
extends CodeClimateReporter<LintFileReport, SummaryLintReportRecord> {
1820
LintCodeClimateReporter(IOSink output, {bool gitlabCompatible = false})
1921
: super(
2022
output,
2123
gitlabCompatible: gitlabCompatible,
2224
);
2325

2426
@override
25-
Future<void> report(Iterable<LintFileReport> records) async {
27+
Future<void> report(
28+
Iterable<LintFileReport> records, {
29+
Iterable<SummaryLintReportRecord> summary = const [],
30+
}) async {
2631
if (records.isEmpty) {
2732
return;
2833
}

lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@ import '../../../metrics/models/metric_value_level.dart';
77
import '../../../models/issue.dart';
88
import '../../../models/lint_file_report.dart';
99
import '../../../models/report.dart';
10+
import '../../../models/summary_lint_report_record.dart';
1011
import 'lint_console_reporter_helper.dart';
1112

12-
class LintConsoleReporter extends ConsoleReporter<LintFileReport> {
13+
class LintConsoleReporter
14+
extends ConsoleReporter<LintFileReport, SummaryLintReportRecord> {
1315
/// If true will report info about all files even if they're not above warning threshold
1416
final bool reportAll;
1517

@@ -18,7 +20,10 @@ class LintConsoleReporter extends ConsoleReporter<LintFileReport> {
1820
LintConsoleReporter(IOSink output, {this.reportAll = false}) : super(output);
1921

2022
@override
21-
Future<void> report(Iterable<LintFileReport> records) async {
23+
Future<void> report(
24+
Iterable<LintFileReport> records, {
25+
Iterable<SummaryLintReportRecord> summary = const [],
26+
}) async {
2227
if (records.isEmpty) {
2328
return;
2429
}

lib/src/analyzers/lint_analyzer/reporters/reporters_list/github/lint_github_reporter.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@ import 'dart:io';
33
import '../../../../../reporters/models/github_reporter.dart';
44
import '../../../models/lint_file_report.dart';
55
import '../../../models/severity.dart';
6+
import '../../../models/summary_lint_report_record.dart';
67

78
const _deprecationMessage =
89
'DEPRECATED! This reporter is deprecated and will be removed in 5.0.0. You can migrate on our GitHub Action.';
910

10-
class LintGitHubReporter extends GitHubReporter<LintFileReport> {
11+
class LintGitHubReporter
12+
extends GitHubReporter<LintFileReport, SummaryLintReportRecord> {
1113
const LintGitHubReporter(IOSink output) : super(output);
1214

1315
@override
14-
Future<void> report(Iterable<LintFileReport> records) async {
16+
Future<void> report(
17+
Iterable<LintFileReport> records, {
18+
Iterable<SummaryLintReportRecord> summary = const [],
19+
}) async {
1520
if (records.isEmpty) {
1621
return;
1722
}

lib/src/analyzers/lint_analyzer/reporters/reporters_list/html/lint_html_reporter.dart

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import '../../../../../reporters/models/html_reporter.dart';
1010
import '../../../metrics/metrics_list/cyclomatic_complexity/cyclomatic_complexity_metric.dart';
1111
import '../../../metrics/models/metric_value_level.dart';
1212
import '../../../models/lint_file_report.dart';
13+
import '../../../models/summary_lint_report_record.dart';
1314
import '../../utility_selector.dart';
1415
import 'components/icon.dart';
1516
import 'components/issue_details_tooltip.dart';
@@ -60,11 +61,15 @@ class ReportTableRecord {
6061
});
6162
}
6263

63-
class LintHtmlReporter extends HtmlReporter<LintFileReport> {
64+
class LintHtmlReporter
65+
extends HtmlReporter<LintFileReport, SummaryLintReportRecord> {
6466
LintHtmlReporter(String reportFolder) : super(reportFolder);
6567

6668
@override
67-
Future<void> report(Iterable<LintFileReport> records) async {
69+
Future<void> report(
70+
Iterable<LintFileReport> records, {
71+
Iterable<SummaryLintReportRecord> summary = const [],
72+
}) async {
6873
await super.report(records);
6974

7075
for (final record in records) {

lib/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter.dart

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@ import '../../../models/issue.dart';
1111
import '../../../models/lint_file_report.dart';
1212
import '../../../models/replacement.dart';
1313
import '../../../models/report.dart';
14+
import '../../../models/summary_lint_report_record.dart';
1415

1516
@immutable
16-
class LintJsonReporter extends JsonReporter<LintFileReport> {
17+
class LintJsonReporter
18+
extends JsonReporter<LintFileReport, SummaryLintReportRecord> {
1719
const LintJsonReporter(IOSink output) : super(output, 2);
1820

1921
@override
20-
Future<void> report(Iterable<LintFileReport> records) async {
22+
Future<void> report(
23+
Iterable<LintFileReport> records, {
24+
Iterable<SummaryLintReportRecord> summary = const [],
25+
}) async {
2126
if (records.isEmpty) {
2227
return;
2328
}
@@ -26,6 +31,12 @@ class LintJsonReporter extends JsonReporter<LintFileReport> {
2631
'formatVersion': formatVersion,
2732
'timestamp': getTimestamp(),
2833
'records': records.map(_lintFileReportToJson).toList(),
34+
if (summary.isNotEmpty)
35+
'summary': summary
36+
.map((record) => _summaryLintReportRecordToJson(
37+
record as SummaryLintReportRecord<Object>,
38+
))
39+
.toList(),
2940
});
3041

3142
output.write(encodedReport);
@@ -39,9 +50,24 @@ class LintJsonReporter extends JsonReporter<LintFileReport> {
3950
'antiPatternCases': _issueToJson(report.antiPatternCases),
4051
};
4152

42-
Map<String, Map<String, Object>> _reportToJson(
43-
Map<String, Report> reports,
44-
) =>
53+
Map<String, Object> _summaryLintReportRecordToJson(
54+
SummaryLintReportRecord<Object> record,
55+
) {
56+
final recordValue = record.value;
57+
final recordViolations = record.violations;
58+
59+
return {
60+
'status': record.status.toString(),
61+
'title': record.title,
62+
'value': recordValue is Iterable ? recordValue.toList() : recordValue,
63+
if (recordViolations != null)
64+
'violations': recordViolations is Iterable
65+
? recordViolations.toList()
66+
: recordViolations,
67+
};
68+
}
69+
70+
Map<String, Map<String, Object>> _reportToJson(Map<String, Report> reports) =>
4571
reports.map((key, value) => MapEntry(key, {
4672
'codeSpan': _sourceSpanToJson(value.location),
4773
'metrics': _metricValuesToJson(value.metrics),

0 commit comments

Comments
 (0)