Skip to content

Commit a75eb7e

Browse files
committed
Added uncovered files detection issue #529
1 parent 04667d7 commit a75eb7e

File tree

4 files changed

+68
-17
lines changed

4 files changed

+68
-17
lines changed

pkgs/coverage/analysis_options.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
include: package:dart_flutter_team_lints/analysis_options.yaml
22

33
analyzer:
4+
errors:
5+
unnecessary_this: ignore
46
language:
57
strict-casts: true
68

pkgs/coverage/lib/src/formatter.dart

+49-17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
// ignore_for_file: unnecessary_this
6+
57
import 'package:glob/glob.dart';
68
import 'package:path/path.dart' as p;
79

@@ -78,26 +80,27 @@ extension FileHitMapsFormatter on Map<String, HitMap> {
7880
String? basePath,
7981
List<String>? reportOn,
8082
Set<Glob>? ignoreGlobs,
83+
bool Function(String path)? includeUncovered,
8184
}) {
8285
final pathFilter = _getPathFilter(
8386
reportOn: reportOn,
8487
ignoreGlobs: ignoreGlobs,
8588
);
8689
final buf = StringBuffer();
90+
91+
// Get all Dart files in the project
92+
final allDartFiles = resolver.listAllDartFiles().toSet();
93+
final coveredFiles = this.keys.toSet();
94+
final uncoveredFiles = allDartFiles.difference(coveredFiles);
95+
8796
for (final entry in entries) {
8897
final v = entry.value;
8998
final lineHits = v.lineHits;
9099
final funcHits = v.funcHits;
91100
final funcNames = v.funcNames;
92101
final branchHits = v.branchHits;
93102
var source = resolver.resolve(entry.key);
94-
if (source == null) {
95-
continue;
96-
}
97-
98-
if (!pathFilter(source)) {
99-
continue;
100-
}
103+
if (source == null || !pathFilter(source)) continue;
101104

102105
if (basePath != null) {
103106
source = p.relative(source, from: basePath);
@@ -129,6 +132,21 @@ extension FileHitMapsFormatter on Map<String, HitMap> {
129132
buf.write('end_of_record\n');
130133
}
131134

135+
// Add uncovered files if allowed
136+
for (final file in uncoveredFiles) {
137+
if (includeUncovered != null && !includeUncovered(file)) continue;
138+
var source = resolver.resolve(file);
139+
if (source == null || !pathFilter(source)) continue;
140+
if (basePath != null) {
141+
source = p.relative(source, from: basePath);
142+
}
143+
144+
buf.write('SF:$source\n');
145+
buf.write('LF:0\n');
146+
buf.write('LH:0\n');
147+
buf.write('end_of_record\n');
148+
}
149+
132150
return buf.toString();
133151
}
134152

@@ -144,12 +162,19 @@ extension FileHitMapsFormatter on Map<String, HitMap> {
144162
Set<Glob>? ignoreGlobs,
145163
bool reportFuncs = false,
146164
bool reportBranches = false,
165+
bool Function(String path)? includeUncovered,
147166
}) async {
148167
final pathFilter = _getPathFilter(
149168
reportOn: reportOn,
150169
ignoreGlobs: ignoreGlobs,
151170
);
152171
final buf = StringBuffer();
172+
173+
// Get all Dart files in the project
174+
final allDartFiles = resolver.listAllDartFiles().toSet();
175+
final coveredFiles = this.keys.toSet();
176+
final uncoveredFiles = allDartFiles.difference(coveredFiles);
177+
153178
for (final entry in entries) {
154179
final v = entry.value;
155180
if (reportFuncs && v.funcHits == null) {
@@ -171,18 +196,10 @@ extension FileHitMapsFormatter on Map<String, HitMap> {
171196
? v.branchHits!
172197
: v.lineHits;
173198
final source = resolver.resolve(entry.key);
174-
if (source == null) {
175-
continue;
176-
}
177-
178-
if (!pathFilter(source)) {
179-
continue;
180-
}
199+
if (source == null || !pathFilter(source)) continue;
181200

182201
final lines = await loader.load(source);
183-
if (lines == null) {
184-
continue;
185-
}
202+
if (lines == null) continue;
186203
buf.writeln(source);
187204
for (var line = 1; line <= lines.length; line++) {
188205
var prefix = _prefix;
@@ -193,6 +210,20 @@ extension FileHitMapsFormatter on Map<String, HitMap> {
193210
}
194211
}
195212

213+
// Add uncovered files if allowed
214+
for (final file in uncoveredFiles) {
215+
if (includeUncovered != null && !includeUncovered(file)) continue;
216+
final source = resolver.resolve(file);
217+
if (source == null || !pathFilter(source)) continue;
218+
219+
final lines = await loader.load(source);
220+
if (lines == null) continue;
221+
buf.writeln(source);
222+
for (final line in lines) {
223+
buf.writeln(' |$line');
224+
}
225+
}
226+
196227
return buf.toString();
197228
}
198229
}
@@ -221,3 +252,4 @@ _PathFilter _getPathFilter({List<String>? reportOn, Set<Glob>? ignoreGlobs}) {
221252
return true;
222253
};
223254
}
255+

pkgs/coverage/lib/src/resolver.dart

+13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ import 'package:path/path.dart' as p;
99

1010
/// [Resolver] resolves imports with respect to a given environment.
1111
class Resolver {
12+
/// Returns a list of all Dart files in the project.
13+
List<String> listAllDartFiles({String directoryPath = '.'}) {
14+
final dir = Directory(directoryPath);
15+
if (!dir.existsSync()) return [];
16+
17+
return dir
18+
.listSync(recursive: true)
19+
.whereType<File>()
20+
.where((file) => file.path.endsWith('.dart'))
21+
.map((file) => file.path)
22+
.toList();
23+
}
24+
1225
@Deprecated('Use Resolver.create')
1326
Resolver({this.packagesPath, this.sdkRoot})
1427
: _packages = packagesPath != null ? _parsePackages(packagesPath) : null,

pkgs/coverage/test/run_and_collect_test.dart

+4
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ class ThrowingResolver implements Resolver {
6969

7070
@override
7171
String? get sdkRoot => throw UnimplementedError();
72+
73+
@override
74+
List<String> listAllDartFiles({String directoryPath = '.'}) =>
75+
throw UnimplementedError();
7276
}
7377

7478
void checkIgnoredLinesInFilesCache(

0 commit comments

Comments
 (0)