Skip to content
This repository was archived by the owner on Aug 28, 2024. It is now read-only.

Commit 43ac0e3

Browse files
authored
Add --ignore-files option to exclude files from code coverage using path patterns (#496)
* Add --ignore-files option, update tests * Simplify checking if any glob matches the source * Move logic to _getPathFilter * Remove unused variable, avoid excessive calls to canonicalize * Flatten ifs * Avoid exceeding line length limit * Add missing expects * Remove junk
1 parent 5ccac01 commit 43ac0e3

File tree

8 files changed

+203
-65
lines changed

8 files changed

+203
-65
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
- Require Dart ^3.4
44
- Fix bug where some ranges were able to bypass the `--scope-output` filters.
5+
- Add --ignore-files option allowing to exclude files from coverage reports using glob patterns
56

67
## 1.8.0
78

bin/format_coverage.dart

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'dart:io';
66

77
import 'package:args/args.dart';
88
import 'package:coverage/coverage.dart';
9+
import 'package:glob/glob.dart';
910
import 'package:path/path.dart' as p;
1011

1112
/// [Environment] stores gathered arguments information.
@@ -24,6 +25,7 @@ class Environment {
2425
required this.prettyPrintFunc,
2526
required this.prettyPrintBranch,
2627
required this.reportOn,
28+
required this.ignoreFiles,
2729
required this.sdkRoot,
2830
required this.verbose,
2931
required this.workers,
@@ -42,6 +44,7 @@ class Environment {
4244
bool prettyPrintFunc;
4345
bool prettyPrintBranch;
4446
List<String>? reportOn;
47+
List<String>? ignoreFiles;
4548
String? sdkRoot;
4649
bool verbose;
4750
int workers;
@@ -76,6 +79,8 @@ Future<void> main(List<String> arguments) async {
7679
print('Done creating global hitmap. Took ${clock.elapsedMilliseconds} ms.');
7780
}
7881

82+
final ignoreGlobs = env.ignoreFiles?.map(Glob.new).toSet();
83+
7984
String output;
8085
final resolver = env.bazel
8186
? BazelResolver(workspacePath: env.bazelWorkspace)
@@ -88,12 +93,15 @@ Future<void> main(List<String> arguments) async {
8893
if (env.prettyPrint) {
8994
output = await hitmap.prettyPrint(resolver, loader,
9095
reportOn: env.reportOn,
96+
ignoreGlobs: ignoreGlobs,
9197
reportFuncs: env.prettyPrintFunc,
9298
reportBranches: env.prettyPrintBranch);
9399
} else {
94100
assert(env.lcov);
95101
output = hitmap.formatLcov(resolver,
96-
reportOn: env.reportOn, basePath: env.baseDirectory);
102+
reportOn: env.reportOn,
103+
ignoreGlobs: ignoreGlobs,
104+
basePath: env.baseDirectory);
97105
}
98106

99107
env.output.write(output);
@@ -124,50 +132,54 @@ Future<void> main(List<String> arguments) async {
124132
Environment parseArgs(List<String> arguments) {
125133
final parser = ArgParser();
126134

127-
parser.addOption('sdk-root', abbr: 's', help: 'path to the SDK root');
128-
parser.addOption('packages',
129-
help: '[DEPRECATED] path to the package spec file');
130-
parser.addOption('package',
131-
help: 'root directory of the package', defaultsTo: '.');
132-
parser.addOption('in', abbr: 'i', help: 'input(s): may be file or directory');
133-
parser.addOption('out',
134-
abbr: 'o', defaultsTo: 'stdout', help: 'output: may be file or stdout');
135-
parser.addMultiOption('report-on',
136-
help: 'which directories or files to report coverage on');
137-
parser.addOption('workers',
138-
abbr: 'j', defaultsTo: '1', help: 'number of workers');
139-
parser.addOption('bazel-workspace',
140-
defaultsTo: '', help: 'Bazel workspace directory');
141-
parser.addOption('base-directory',
142-
abbr: 'b',
143-
help: 'the base directory relative to which source paths are output');
144-
parser.addFlag('bazel',
145-
defaultsTo: false, help: 'use Bazel-style path resolution');
146-
parser.addFlag('pretty-print',
147-
abbr: 'r',
148-
negatable: false,
149-
help: 'convert line coverage data to pretty print format');
150-
parser.addFlag('pretty-print-func',
151-
abbr: 'f',
135+
parser
136+
..addOption('sdk-root', abbr: 's', help: 'path to the SDK root')
137+
..addOption('packages', help: '[DEPRECATED] path to the package spec file')
138+
..addOption('package',
139+
help: 'root directory of the package', defaultsTo: '.')
140+
..addOption('in', abbr: 'i', help: 'input(s): may be file or directory')
141+
..addOption('out',
142+
abbr: 'o', defaultsTo: 'stdout', help: 'output: may be file or stdout')
143+
..addMultiOption('report-on',
144+
help: 'which directories or files to report coverage on')
145+
..addOption('workers',
146+
abbr: 'j', defaultsTo: '1', help: 'number of workers')
147+
..addOption('bazel-workspace',
148+
defaultsTo: '', help: 'Bazel workspace directory')
149+
..addOption('base-directory',
150+
abbr: 'b',
151+
help: 'the base directory relative to which source paths are output')
152+
..addFlag('bazel',
153+
defaultsTo: false, help: 'use Bazel-style path resolution')
154+
..addFlag('pretty-print',
155+
abbr: 'r',
156+
negatable: false,
157+
help: 'convert line coverage data to pretty print format')
158+
..addFlag('pretty-print-func',
159+
abbr: 'f',
160+
negatable: false,
161+
help: 'convert function coverage data to pretty print format')
162+
..addFlag('pretty-print-branch',
163+
negatable: false,
164+
help: 'convert branch coverage data to pretty print format')
165+
..addFlag('lcov',
166+
abbr: 'l',
167+
negatable: false,
168+
help: 'convert coverage data to lcov format')
169+
..addFlag('verbose', abbr: 'v', negatable: false, help: 'verbose output')
170+
..addFlag(
171+
'check-ignore',
172+
abbr: 'c',
152173
negatable: false,
153-
help: 'convert function coverage data to pretty print format');
154-
parser.addFlag('pretty-print-branch',
155-
negatable: false,
156-
help: 'convert branch coverage data to pretty print format');
157-
parser.addFlag('lcov',
158-
abbr: 'l',
159-
negatable: false,
160-
help: 'convert coverage data to lcov format');
161-
parser.addFlag('verbose',
162-
abbr: 'v', negatable: false, help: 'verbose output');
163-
parser.addFlag(
164-
'check-ignore',
165-
abbr: 'c',
166-
negatable: false,
167-
help: 'check for coverage ignore comments.'
168-
' Not supported in web coverage.',
169-
);
170-
parser.addFlag('help', abbr: 'h', negatable: false, help: 'show this help');
174+
help: 'check for coverage ignore comments.'
175+
' Not supported in web coverage.',
176+
)
177+
..addMultiOption(
178+
'ignore-files',
179+
defaultsTo: [],
180+
help: 'Ignore files by glob patterns',
181+
)
182+
..addFlag('help', abbr: 'h', negatable: false, help: 'show this help');
171183

172184
final args = parser.parse(arguments);
173185

@@ -261,6 +273,7 @@ Environment parseArgs(List<String> arguments) {
261273
}
262274

263275
final checkIgnore = args['check-ignore'] as bool;
276+
final ignoredGlobs = args['ignore-files'] as List<String>;
264277
final verbose = args['verbose'] as bool;
265278
return Environment(
266279
baseDirectory: baseDirectory,
@@ -276,6 +289,7 @@ Environment parseArgs(List<String> arguments) {
276289
prettyPrintFunc: prettyPrintFunc,
277290
prettyPrintBranch: prettyPrintBranch,
278291
reportOn: reportOn,
292+
ignoreFiles: ignoredGlobs,
279293
sdkRoot: sdkRoot,
280294
verbose: verbose,
281295
workers: workers);

lib/src/formatter.dart

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
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+
import 'package:glob/glob.dart';
56
import 'package:path/path.dart' as p;
67

78
import 'hitmap.dart';
@@ -76,8 +77,12 @@ extension FileHitMapsFormatter on Map<String, HitMap> {
7677
Resolver resolver, {
7778
String? basePath,
7879
List<String>? reportOn,
80+
Set<Glob>? ignoreGlobs,
7981
}) {
80-
final pathFilter = _getPathFilter(reportOn);
82+
final pathFilter = _getPathFilter(
83+
reportOn: reportOn,
84+
ignoreGlobs: ignoreGlobs,
85+
);
8186
final buf = StringBuffer();
8287
for (final entry in entries) {
8388
final v = entry.value;
@@ -136,10 +141,14 @@ extension FileHitMapsFormatter on Map<String, HitMap> {
136141
Resolver resolver,
137142
Loader loader, {
138143
List<String>? reportOn,
144+
Set<Glob>? ignoreGlobs,
139145
bool reportFuncs = false,
140146
bool reportBranches = false,
141147
}) async {
142-
final pathFilter = _getPathFilter(reportOn);
148+
final pathFilter = _getPathFilter(
149+
reportOn: reportOn,
150+
ignoreGlobs: ignoreGlobs,
151+
);
143152
final buf = StringBuffer();
144153
for (final entry in entries) {
145154
final v = entry.value;
@@ -192,10 +201,23 @@ const _prefix = ' ';
192201

193202
typedef _PathFilter = bool Function(String path);
194203

195-
_PathFilter _getPathFilter(List<String>? reportOn) {
196-
if (reportOn == null) return (String path) => true;
204+
_PathFilter _getPathFilter({List<String>? reportOn, Set<Glob>? ignoreGlobs}) {
205+
if (reportOn == null && ignoreGlobs == null) return (String path) => true;
197206

198-
final absolutePaths = reportOn.map(p.canonicalize).toList();
199-
return (String path) =>
200-
absolutePaths.any((item) => p.canonicalize(path).startsWith(item));
207+
final absolutePaths = reportOn?.map(p.canonicalize).toList();
208+
209+
return (String path) {
210+
final canonicalizedPath = p.canonicalize(path);
211+
212+
if (absolutePaths != null &&
213+
!absolutePaths.any(canonicalizedPath.startsWith)) {
214+
return false;
215+
}
216+
if (ignoreGlobs != null &&
217+
ignoreGlobs.any((glob) => glob.matches(canonicalizedPath))) {
218+
return false;
219+
}
220+
221+
return true;
222+
};
201223
}

pubspec.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ environment:
88

99
dependencies:
1010
args: ^2.0.0
11+
glob: ^2.1.2
1112
logging: ^1.0.0
1213
package_config: ^2.0.0
1314
path: ^1.8.0

0 commit comments

Comments
 (0)