From a378445264275b1d3629425e7ea2a520261ae2f9 Mon Sep 17 00:00:00 2001 From: Dmitry Krutskikh Date: Sat, 6 Nov 2021 18:18:12 +0300 Subject: [PATCH 1/5] refactor: rename buildRecordStub to buildReportStub --- test/src/analyzers/lint_analyzer/models/report_test.dart | 2 +- .../html/components/report_details_tooltip_test.dart | 2 +- .../lint_analyzer/reporters/utility_selector_test.dart | 6 +++--- test/stubs_builders.dart | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/test/src/analyzers/lint_analyzer/models/report_test.dart b/test/src/analyzers/lint_analyzer/models/report_test.dart index bea3a498b6..e7a89d41f8 100644 --- a/test/src/analyzers/lint_analyzer/models/report_test.dart +++ b/test/src/analyzers/lint_analyzer/models/report_test.dart @@ -19,7 +19,7 @@ void main() { late Report report; setUp(() { - report = buildRecordStub(metrics: [ + report = buildReportStub(metrics: [ buildMetricValueStub( id: metric1Id, value: 10, diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/html/components/report_details_tooltip_test.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/html/components/report_details_tooltip_test.dart index c622ea64e4..6801c6b6a4 100644 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/html/components/report_details_tooltip_test.dart +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/html/components/report_details_tooltip_test.dart @@ -12,7 +12,7 @@ void main() { () { expect( renderDetailsTooltip( - buildRecordStub( + buildReportStub( metrics: [ buildMetricValueStub( id: 'metric', diff --git a/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart b/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart index 6b789c8a7b..4691e1e007 100644 --- a/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart +++ b/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart @@ -20,7 +20,7 @@ void main() { path: '/home/developer/work/project/example.dart', relativePath: 'example.dart', classes: Map.unmodifiable({ - 'class': buildRecordStub(metrics: const [ + 'class': buildReportStub(metrics: const [ MetricValue( metricsId: NumberOfMethodsMetric.metricId, documentation: MetricDocumentation( @@ -35,7 +35,7 @@ void main() { comment: '', ), ]), - 'mixin': buildRecordStub(metrics: const [ + 'mixin': buildReportStub(metrics: const [ MetricValue( metricsId: NumberOfMethodsMetric.metricId, documentation: MetricDocumentation( @@ -50,7 +50,7 @@ void main() { comment: '', ), ]), - 'extension': buildRecordStub(metrics: const [ + 'extension': buildReportStub(metrics: const [ MetricValue( metricsId: NumberOfMethodsMetric.metricId, documentation: MetricDocumentation( diff --git a/test/stubs_builders.dart b/test/stubs_builders.dart index 9efa528ed3..87d624986e 100644 --- a/test/stubs_builders.dart +++ b/test/stubs_builders.dart @@ -35,7 +35,7 @@ MetricValue buildMetricValueStub({ comment: '', ); -Report buildRecordStub({ +Report buildReportStub({ SourceSpanBase? location, Iterable> metrics = const [], }) { From 6233980db25d4ad987068cca23fb36262ecacf07 Mon Sep 17 00:00:00 2001 From: Dmitry Krutskikh Date: Sat, 6 Nov 2021 18:19:12 +0300 Subject: [PATCH 2/5] feat: introduce file metric --- .../metrics/models/file_metric.dart | 43 +++++++++++++++++++ .../lint_analyzer/models/entity_type.dart | 5 ++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 lib/src/analyzers/lint_analyzer/metrics/models/file_metric.dart diff --git a/lib/src/analyzers/lint_analyzer/metrics/models/file_metric.dart b/lib/src/analyzers/lint_analyzer/metrics/models/file_metric.dart new file mode 100644 index 0000000000..8f75474b88 --- /dev/null +++ b/lib/src/analyzers/lint_analyzer/metrics/models/file_metric.dart @@ -0,0 +1,43 @@ +import 'package:analyzer/dart/ast/ast.dart'; + +import '../../models/internal_resolved_unit_result.dart'; +import '../../models/scoped_class_declaration.dart'; +import '../../models/scoped_function_declaration.dart'; +import 'metric.dart'; +import 'metric_documentation.dart'; +import 'metric_value.dart'; +import 'metric_value_level.dart'; + +/// An interface for metrics that compute a value for a file aka compilation unit node. +abstract class FileMetric extends Metric { + /// Initialize a newly created [FileMetric]. + const FileMetric({ + required String id, + required MetricDocumentation documentation, + required T? threshold, + required MetricValueLevel Function(T, T?) levelComputer, + }) : super( + id: id, + documentation: documentation, + threshold: threshold, + levelComputer: levelComputer, + ); + + @override + bool supports( + AstNode node, + Iterable classDeclarations, + Iterable functionDeclarations, + InternalResolvedUnitResult source, + Iterable otherMetricsValues, + ) => + node is CompilationUnit; + + @override + String? nodeType( + AstNode node, + Iterable classDeclarations, + Iterable functionDeclarations, + ) => + null; +} diff --git a/lib/src/analyzers/lint_analyzer/models/entity_type.dart b/lib/src/analyzers/lint_analyzer/models/entity_type.dart index d1b215e79a..f79bc204f4 100644 --- a/lib/src/analyzers/lint_analyzer/models/entity_type.dart +++ b/lib/src/analyzers/lint_analyzer/models/entity_type.dart @@ -5,11 +5,14 @@ class EntityType { /// The entity representing a class, mixin or extension. static const classEntity = EntityType._('class'); + /// The entity representing a whole file. + static const fileEntity = EntityType._('file'); + /// The entity representing a class method or constructor, function, getter or setter. static const methodEntity = EntityType._('method'); /// A list containing all of the enum values that are defined. - static const values = [classEntity, methodEntity]; + static const values = [classEntity, fileEntity, methodEntity]; final String _value; From 72fc8e5529c4ad093a0b378c944d249380c88bc2 Mon Sep 17 00:00:00 2001 From: Dmitry Krutskikh Date: Sat, 6 Nov 2021 18:19:54 +0300 Subject: [PATCH 3/5] feat: introduce file metrics report --- lib/src/analyzers/lint_analyzer/lint_analyzer.dart | 12 ++++++++++++ .../lint_analyzer/models/lint_file_report.dart | 4 ++++ .../analyzers/lint_analyzer/lint_analyzer_test.dart | 4 ++++ .../reporters_list/lint_github_reporter_test.dart | 4 ++++ .../reporters/reporters_list/report_example.dart | 4 ++++ .../reporters/utility_selector_test.dart | 1 + .../lint_analyzer/utils/report_utils_test.dart | 4 ++++ 7 files changed, 33 insertions(+) diff --git a/lib/src/analyzers/lint_analyzer/lint_analyzer.dart b/lib/src/analyzers/lint_analyzer/lint_analyzer.dart index 708b6ba056..e40c7538e6 100644 --- a/lib/src/analyzers/lint_analyzer/lint_analyzer.dart +++ b/lib/src/analyzers/lint_analyzer/lint_analyzer.dart @@ -208,6 +208,12 @@ class LintAnalyzer { return LintFileReport( path: filePath, relativePath: relativePath, + file: Report( + location: + nodeLocation(node: internalResult.unit, source: internalResult), + metrics: const [], + declaration: internalResult.unit, + ), classes: Map.unmodifiable(classMetrics .map((key, value) => MapEntry(key.name, value))), functions: Map.unmodifiable(functionMetrics.map( @@ -221,6 +227,12 @@ class LintAnalyzer { return LintFileReport( path: filePath, relativePath: relativePath, + file: Report( + location: + nodeLocation(node: internalResult.unit, source: internalResult), + metrics: const [], + declaration: internalResult.unit, + ), classes: const {}, functions: const {}, issues: issues, diff --git a/lib/src/analyzers/lint_analyzer/models/lint_file_report.dart b/lib/src/analyzers/lint_analyzer/models/lint_file_report.dart index 92049d989a..5dc5f75700 100644 --- a/lib/src/analyzers/lint_analyzer/models/lint_file_report.dart +++ b/lib/src/analyzers/lint_analyzer/models/lint_file_report.dart @@ -15,6 +15,9 @@ class LintFileReport implements FileReport { @override final String relativePath; + /// The metrics report about the target file. + final Report file; + /// The all classes reports in the target file. final Map classes; @@ -30,6 +33,7 @@ class LintFileReport implements FileReport { const LintFileReport({ required this.path, required this.relativePath, + required this.file, required this.classes, required this.functions, required this.issues, diff --git a/test/src/analyzers/lint_analyzer/lint_analyzer_test.dart b/test/src/analyzers/lint_analyzer/lint_analyzer_test.dart index 4af8299d72..9c045e7cb4 100644 --- a/test/src/analyzers/lint_analyzer/lint_analyzer_test.dart +++ b/test/src/analyzers/lint_analyzer/lint_analyzer_test.dart @@ -9,6 +9,8 @@ import 'package:dart_code_metrics/src/analyzers/lint_analyzer/models/report.dart import 'package:path/path.dart' as p; import 'package:test/test.dart'; +import '../../../stubs_builders.dart'; + void main() { group( 'LintAnalyzer', @@ -170,6 +172,7 @@ void main() { LintFileReport( path: '/home/dev/project/bin/example.dart', relativePath: 'bin/example.dart', + file: buildReportStub(), classes: Map.unmodifiable({}), functions: Map.unmodifiable({}), issues: const [], @@ -178,6 +181,7 @@ void main() { LintFileReport( path: '/home/dev/project/lib/example.dart', relativePath: 'lib/example.dart', + file: buildReportStub(), classes: Map.unmodifiable({}), functions: Map.unmodifiable({}), issues: const [], diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_github_reporter_test.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_github_reporter_test.dart index 027455d818..ce6625a63a 100644 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_github_reporter_test.dart +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_github_reporter_test.dart @@ -11,6 +11,8 @@ import 'package:mocktail/mocktail.dart'; import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; +import '../../../../../stubs_builders.dart'; + class IOSinkMock extends Mock implements IOSink {} void main() { @@ -34,6 +36,7 @@ void main() { LintFileReport( path: fullPath, relativePath: 'example.dart', + file: buildReportStub(), classes: Map.unmodifiable({}), functions: Map.unmodifiable({}), issues: const [], @@ -74,6 +77,7 @@ void main() { LintFileReport( path: fullPath, relativePath: 'example.dart', + file: buildReportStub(), classes: Map.unmodifiable({}), functions: Map.unmodifiable({}), issues: [ diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart index 9306385181..ff2247c202 100644 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart @@ -14,6 +14,8 @@ import 'package:dart_code_metrics/src/analyzers/lint_analyzer/models/summary_lin import 'package:mocktail/mocktail.dart'; import 'package:source_span/source_span.dart'; +import '../../../../../stubs_builders.dart'; + const src1Path = 'test/resources/abstract_class.dart'; const src2Path = 'test/resources/class_with_factory_constructors.dart'; @@ -136,6 +138,7 @@ final Iterable testReport = [ LintFileReport( path: src1Path, relativePath: src1Path, + file: buildReportStub(), classes: {'class': _class1Report}, functions: { 'class.constructor': _function1Report, @@ -147,6 +150,7 @@ final Iterable testReport = [ LintFileReport( path: src2Path, relativePath: src2Path, + file: buildReportStub(), classes: const {}, functions: {'function': _function3Report}, issues: [_issueReport1], diff --git a/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart b/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart index 4691e1e007..86e80e8757 100644 --- a/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart +++ b/test/src/analyzers/lint_analyzer/reporters/utility_selector_test.dart @@ -19,6 +19,7 @@ void main() { LintFileReport( path: '/home/developer/work/project/example.dart', relativePath: 'example.dart', + file: buildReportStub(), classes: Map.unmodifiable({ 'class': buildReportStub(metrics: const [ MetricValue( diff --git a/test/src/analyzers/lint_analyzer/utils/report_utils_test.dart b/test/src/analyzers/lint_analyzer/utils/report_utils_test.dart index 19dc4e0c21..652ff3938e 100644 --- a/test/src/analyzers/lint_analyzer/utils/report_utils_test.dart +++ b/test/src/analyzers/lint_analyzer/utils/report_utils_test.dart @@ -25,6 +25,7 @@ void main() { LintFileReport( path: fullPathStub, relativePath: relativePathStub, + file: buildReportStub(), classes: const {}, functions: {'a': buildFunctionRecordStub(metrics: [])}, issues: const [], @@ -36,6 +37,7 @@ void main() { LintFileReport( path: fullPathStub, relativePath: relativePathStub, + file: buildReportStub(), classes: Map.unmodifiable({}), functions: Map.unmodifiable({ 'a': buildFunctionRecordStub( @@ -65,6 +67,7 @@ void main() { LintFileReport( path: fullPathStub2, relativePath: relativePathStub2, + file: buildReportStub(), classes: Map.unmodifiable({}), functions: Map.unmodifiable({ 'a': buildFunctionRecordStub( @@ -88,6 +91,7 @@ void main() { LintFileReport( path: fullPathStub3, relativePath: relativePathStub3, + file: buildReportStub(), classes: Map.unmodifiable({}), functions: Map.unmodifiable({ 'a': buildFunctionRecordStub( From 46ec3d449644dc143a77c6edc4d704b4681e6100 Mon Sep 17 00:00:00 2001 From: Dmitry Krutskikh Date: Sat, 6 Nov 2021 21:54:21 +0300 Subject: [PATCH 4/5] feat: report file metrics in console, code climate and json reporters --- .../lint_code_climate_reporter.dart | 2 +- .../console/lint_console_reporter.dart | 36 ++++----- .../console/lint_console_reporter_helper.dart | 6 +- .../json/lint_json_reporter.dart | 1 + .../lint_code_climate_reporter_test.dart | 75 +++++++++++++++++++ .../lint_console_reporter_helper_test.dart | 2 +- .../lint_console_reporter_test.dart | 5 +- .../json/lint_json_reporter_test.dart | 12 +++ .../lint_code_climate_reporter_test.dart | 49 ------------ .../reporters_list/report_example.dart | 22 +++++- website/docs/cli/analyze.md | 1 + 11 files changed, 137 insertions(+), 74 deletions(-) create mode 100644 test/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter_test.dart rename test/src/analyzers/lint_analyzer/reporters/reporters_list/{ => console}/lint_console_reporter_helper_test.dart (98%) rename test/src/analyzers/lint_analyzer/reporters/reporters_list/{ => console}/lint_console_reporter_test.dart (90%) delete mode 100644 test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_code_climate_reporter_test.dart diff --git a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter.dart b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter.dart index 6cc235f388..39942cc0d7 100644 --- a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter.dart +++ b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter.dart @@ -56,7 +56,7 @@ class LintCodeClimateReporter record.relativePath, ), ..._reportsToCodeClimate( - [...record.functions.values, ...record.classes.values], + [record.file, ...record.classes.values, ...record.functions.values], record.relativePath, ), ]; diff --git a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter.dart b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter.dart index 940f8a6a07..e9a910818e 100644 --- a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter.dart +++ b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter.dart @@ -33,8 +33,9 @@ class LintConsoleReporter for (final file in records) { final lines = [ + ..._reportMetrics('', file.file), ..._reportIssues([...file.issues, ...file.antiPatternCases]), - ..._reportMetrics({...file.classes, ...file.functions}), + ..._reportEntityMetrics({...file.classes, ...file.functions}), ]; if (lines.isNotEmpty) { @@ -50,29 +51,28 @@ class LintConsoleReporter a.location.start.offset.compareTo(b.location.start.offset))) .map(_helper.getIssueMessage); - Iterable _reportMetrics(Map reports) => + Iterable _reportEntityMetrics(Map reports) => (reports.entries.toList() ..sort((a, b) => a.value.location.start.offset .compareTo(b.value.location.start.offset))) - .expand((entry) { - final source = entry.key; - final report = entry.value; + .expand((entry) => _reportMetrics(entry.key, entry.value)); - final reportLevel = report.metricsLevel; - if (reportAll || isReportLevel(reportLevel)) { - final violations = [ - for (final metric in report.metrics) - if (reportAll || _isNeedToReport(metric)) - _helper.getMetricReport(metric), - ]; + Iterable _reportMetrics(String source, Report report) { + final reportLevel = report.metricsLevel; + if (reportAll || isReportLevel(reportLevel)) { + final violations = [ + for (final metric in report.metrics) + if (reportAll || _isNeedToReport(metric)) + _helper.getMetricReport(metric), + ]; - return [ - _helper.getMetricMessage(reportLevel, source, violations), - ]; - } + return [ + _helper.getMetricMessage(reportLevel, source, violations), + ]; + } - return []; - }); + return []; + } bool _isNeedToReport(MetricValue metric) => metric.level > MetricValueLevel.none; diff --git a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_helper.dart b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_helper.dart index b814bf6087..2de930c0e8 100644 --- a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_helper.dart +++ b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_helper.dart @@ -40,13 +40,13 @@ class LintConsoleReporterHelper { ) { final color = _colorPens[violationLevel]; if (color != null) { - final normalizedLabel = _normalize( + final normalizedLabel = color(_normalize( violationLevel != MetricValueLevel.none ? violationLevel.toString().capitalize() : '', - ); + )); - return '${color(normalizedLabel)}$source - ${violations.join(', ')}'; + return '$normalizedLabel${source.isNotEmpty ? '$source - ' : ''}${violations.join(', ')}'; } throw StateError('Unexpected violation level.'); diff --git a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter.dart b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter.dart index 5fd7367cf4..76f7566432 100644 --- a/lib/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter.dart +++ b/lib/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter.dart @@ -47,6 +47,7 @@ class LintJsonReporter Map _lintFileReportToJson(LintFileReport report) => { 'path': report.relativePath, + 'fileMetrics': _metricValuesToJson(report.file.metrics), 'classes': _reportToJson(report.classes), 'functions': _reportToJson(report.functions), 'issues': _issueToJson(report.issues), diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter_test.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter_test.dart new file mode 100644 index 0000000000..7cdc6d4841 --- /dev/null +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter_test.dart @@ -0,0 +1,75 @@ +import 'dart:io'; + +import 'package:dart_code_metrics/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter.dart'; +import 'package:mocktail/mocktail.dart'; +import 'package:test/test.dart'; + +import '../report_example.dart'; + +class IOSinkMock extends Mock implements IOSink {} + +void main() { + group('LintCodeClimateReporter.report report about', () { + late IOSinkMock output; // ignore: close_sinks + late IOSinkMock gitlabOutput; // ignore: close_sinks + + late LintCodeClimateReporter _reporter; + late LintCodeClimateReporter _gitlabReporter; + + setUp(() { + output = IOSinkMock(); + gitlabOutput = IOSinkMock(); + + _reporter = LintCodeClimateReporter(output); + _gitlabReporter = + LintCodeClimateReporter(gitlabOutput, gitlabCompatible: true); + }); + + test('empty report', () async { + await _reporter.report([]); + await _gitlabReporter.report([]); + + verifyNever(() => output.writeln(any())); + verifyNever(() => gitlabOutput.writeln(any())); + }); + + test('complex report', () async { + await _reporter.report(testReport); + await _gitlabReporter.report(testReport); + + final captured = verify( + () => output.writeln(captureAny()), + ).captured.cast(); + final gitlabCaptured = verify( + () => gitlabOutput.writeln(captureAny()), + ).captured.cast(); + + expect( + captured, + equals( + [ + '{"type":"issue","check_name":"file-metric-id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/abstract_class.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":12}}},"severity":"info","fingerprint":"7b9ff7e7828edd7e91c3e9ef91e6dcc6"}\x00', + '{"type":"issue","check_name":"id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/abstract_class.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":16}}},"severity":"info","fingerprint":"661469706d480a46dfeea856182f339f"}\x00', + '{"type":"issue","check_name":"id","description":"simple message","categories":["Bug Risk"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"critical","fingerprint":"f25e877a3578c5d4433dfe131b9f98d0"}\x00', + '{"type":"issue","check_name":"designId","description":"simple design message","categories":["Style"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"minor","fingerprint":"4eb25898669ab2a1c20db5d70e2edfb8"}\x00', + '{"type":"issue","check_name":"id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"info","fingerprint":"b1abfce3f198adb690f6d40fc2aea6a5"}\x00', + ], + ), + ); + + // ignore_for_file: missing_whitespace_between_adjacent_strings + expect( + gitlabCaptured.single, + equals( + '[' + '{"type":"issue","check_name":"file-metric-id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/abstract_class.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":12}}},"severity":"info","fingerprint":"7b9ff7e7828edd7e91c3e9ef91e6dcc6"},' + '{"type":"issue","check_name":"id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/abstract_class.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":16}}},"severity":"info","fingerprint":"661469706d480a46dfeea856182f339f"},' + '{"type":"issue","check_name":"id","description":"simple message","categories":["Bug Risk"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"critical","fingerprint":"f25e877a3578c5d4433dfe131b9f98d0"},' + '{"type":"issue","check_name":"designId","description":"simple design message","categories":["Style"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"minor","fingerprint":"4eb25898669ab2a1c20db5d70e2edfb8"},' + '{"type":"issue","check_name":"id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"info","fingerprint":"b1abfce3f198adb690f6d40fc2aea6a5"}' + ']', + ), + ); + }); + }); +} diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_console_reporter_helper_test.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_helper_test.dart similarity index 98% rename from test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_console_reporter_helper_test.dart rename to test/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_helper_test.dart index 605ddc1d85..c1b4ae43e4 100644 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_console_reporter_helper_test.dart +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_helper_test.dart @@ -7,7 +7,7 @@ import 'package:dart_code_metrics/src/analyzers/lint_analyzer/reporters/reporter import 'package:source_span/source_span.dart'; import 'package:test/test.dart'; -import '../../../../../stubs_builders.dart'; +import '../../../../../../stubs_builders.dart'; void main() { group('LintConsoleReporterHelper', () { diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_console_reporter_test.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_test.dart similarity index 90% rename from test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_console_reporter_test.dart rename to test/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_test.dart index 5fad34ef85..d75e8b9c93 100644 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_console_reporter_test.dart +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/console/lint_console_reporter_test.dart @@ -6,7 +6,7 @@ import 'package:dart_code_metrics/src/analyzers/lint_analyzer/reporters/reporter import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; -import 'report_example.dart'; +import '../report_example.dart'; class IOSinkMock extends Mock implements IOSink {} @@ -52,6 +52,7 @@ void main() { equals( [ 'test/resources/abstract_class.dart:', + '\x1B[38;5;11mWarning \x1B[0mmetric1: \x1B[38;5;11m100\x1B[0m', '\x1B[38;5;9mAlarm \x1B[0mclass.constructor - metric2: \x1B[38;5;9m10\x1B[0m', '', 'test/resources/class_with_factory_constructors.dart:', @@ -67,11 +68,13 @@ void main() { equals( [ 'test/resources/abstract_class.dart:', + '\x1B[38;5;11mWarning \x1B[0mmetric1: \x1B[38;5;11m100\x1B[0m', '\x1B[38;5;7m \x1B[0mclass - metric1: \x1B[38;5;7m0\x1B[0m', '\x1B[38;5;9mAlarm \x1B[0mclass.constructor - metric2: \x1B[38;5;9m10\x1B[0m', '\x1B[38;5;7m \x1B[0mclass.method - metric3: \x1B[38;5;7m1\x1B[0m', '', 'test/resources/class_with_factory_constructors.dart:', + '\x1B[38;5;7m \x1B[0mmetric1: \x1B[38;5;7m0\x1B[0m, metric2: \x1B[38;5;7m1\x1B[0m', '\x1B[38;5;11mWarning \x1B[0msimple message : 0:0 : id', '\x1B[38;5;4mStyle \x1B[0msimple design message : 0:0 : designId', '\x1B[38;5;11mWarning \x1B[0mfunction - metric4: \x1B[38;5;11m5\x1B[0m', diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter_test.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter_test.dart index 3818f274a8..c43804e7f6 100644 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter_test.dart +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/json/lint_json_reporter_test.dart @@ -38,6 +38,18 @@ void main() { final recordFirst = (report['records'] as Iterable).first as Map; expect(recordFirst, containsPair('path', src1Path)); + expect( + recordFirst['fileMetrics'], + equals([ + { + 'metricsId': 'file-metric-id', + 'value': 100, + 'level': 'warning', + 'comment': 'metric comment', + 'context': [], + }, + ]), + ); final recordLast = (report['records'] as Iterable).last as Map; expect(recordLast, containsPair('path', src2Path)); diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_code_climate_reporter_test.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_code_climate_reporter_test.dart deleted file mode 100644 index dd25e52c07..0000000000 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/lint_code_climate_reporter_test.dart +++ /dev/null @@ -1,49 +0,0 @@ -import 'dart:io'; - -import 'package:dart_code_metrics/src/analyzers/lint_analyzer/reporters/reporters_list/code_climate/lint_code_climate_reporter.dart'; -import 'package:mocktail/mocktail.dart'; -import 'package:test/test.dart'; - -import 'report_example.dart'; - -class IOSinkMock extends Mock implements IOSink {} - -void main() { - group('LintCodeClimateReporter.report report about', () { - late IOSinkMock output; // ignore: close_sinks - - late LintCodeClimateReporter _reporter; - - setUp(() { - output = IOSinkMock(); - - _reporter = LintCodeClimateReporter(output); - }); - - test('empty report', () async { - await _reporter.report([]); - - verifyNever(() => output.writeln(any())); - }); - - test('complex report', () async { - await _reporter.report(testReport); - - final captured = verify( - () => output.writeln(captureAny()), - ).captured.cast(); - - expect( - captured, - equals( - [ - '{"type":"issue","check_name":"id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/abstract_class.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":16}}},"severity":"info","fingerprint":"661469706d480a46dfeea856182f339f"}\x00', - '{"type":"issue","check_name":"id","description":"simple message","categories":["Bug Risk"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"critical","fingerprint":"f25e877a3578c5d4433dfe131b9f98d0"}\x00', - '{"type":"issue","check_name":"designId","description":"simple design message","categories":["Style"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"minor","fingerprint":"4eb25898669ab2a1c20db5d70e2edfb8"}\x00', - '{"type":"issue","check_name":"id","description":"metric comment","categories":["Complexity"],"location":{"path":"test/resources/class_with_factory_constructors.dart","positions":{"begin":{"line":0,"column":0},"end":{"line":0,"column":20}}},"severity":"info","fingerprint":"b1abfce3f198adb690f6d40fc2aea6a5"}\x00', - ], - ), - ); - }); - }); -} diff --git a/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart b/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart index ff2247c202..426b3310b0 100644 --- a/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart +++ b/test/src/analyzers/lint_analyzer/reporters/reporters_list/report_example.dart @@ -21,6 +21,26 @@ const src2Path = 'test/resources/class_with_factory_constructors.dart'; class _DeclarationMock extends Mock implements Declaration {} +final _file1Report = Report( + location: SourceSpan(SourceLocation(0), SourceLocation(12), 'file content'), + declaration: _DeclarationMock(), + metrics: const [ + MetricValue( + metricsId: 'file-metric-id', + documentation: MetricDocumentation( + name: 'metric1', + shortName: 'MTR1', + brief: '', + measuredType: EntityType.fileEntity, + recomendedThreshold: 0, + ), + value: 100, + level: MetricValueLevel.warning, + comment: 'metric comment', + ), + ], +); + final _class1Report = Report( location: SourceSpan(SourceLocation(0), SourceLocation(10), 'class body'), declaration: _DeclarationMock(), @@ -138,7 +158,7 @@ final Iterable testReport = [ LintFileReport( path: src1Path, relativePath: src1Path, - file: buildReportStub(), + file: _file1Report, classes: {'class': _class1Report}, functions: { 'class.constructor': _function1Report, diff --git a/website/docs/cli/analyze.md b/website/docs/cli/analyze.md index 8b81fdb61e..d696ba1c45 100644 --- a/website/docs/cli/analyze.md +++ b/website/docs/cli/analyze.md @@ -114,6 +114,7 @@ The reporter prints a single JSON object containing meta information and the vio #### The **record** object fields are {#the-record-object-fields-are} - `path` - a relative path to the target file +- `fileMetrics` - an array with target file [metrics](#the-metric-value-object-fields-are) - `classes` - a map with **class name** as the **key** and **[class report](#the-report-object-fields-are)** as the **value** - `functions` - a map with **function name** as the **key** and **[function report](#the-report-object-fields-are)** as the **value** - `issues` - an array of [issues](#the-issue-object-fields-are) detected in the target file From ec3ddd1fa776ead02828804a6e1ddfbf41eea2d5 Mon Sep 17 00:00:00 2001 From: Dmitry Krutskikh Date: Sat, 6 Nov 2021 18:21:31 +0300 Subject: [PATCH 5/5] chore: update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99a07d7acf..ab25505783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased * refactor: make violations field of summary lint report record as integer +* feat: introduce file metrics ## 4.6.0