blob: 732edc56f8e47e30fddb759686e8b87ccd18de80 [file] [edit]
// Copyright (c) 2025, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:io';
import 'package:cli_config/cli_config.dart';
import 'package:path/path.dart' as path;
class CoverageOptions {
const CoverageOptions({
this.outputDirectory,
required this.scopeOutput,
required this.functionCoverage,
required this.branchCoverage,
required this.packageDirectory,
required this.testScript,
});
factory CoverageOptions.fromConfig(
Config options,
CoverageOptions defaultOptions,
String? optionsFilePath,
) {
var outputDirectory =
options.optionalString('output_directory') ??
defaultOptions.outputDirectory;
var packageDirectory =
options.optionalString('package_directory') ??
defaultOptions.packageDirectory;
if (optionsFilePath != null) {
if (outputDirectory != null && !path.isAbsolute(outputDirectory)) {
outputDirectory = path.normalize(
path.absolute(path.dirname(optionsFilePath), outputDirectory),
);
}
if (!path.isAbsolute(packageDirectory)) {
packageDirectory = path.normalize(
path.absolute(path.dirname(optionsFilePath), packageDirectory),
);
}
}
return CoverageOptions(
outputDirectory: outputDirectory,
scopeOutput:
options.optionalStringList('scope_output') ??
defaultOptions.scopeOutput,
functionCoverage:
options.optionalBool('function_coverage') ??
defaultOptions.functionCoverage,
branchCoverage:
options.optionalBool('branch_coverage') ??
defaultOptions.branchCoverage,
packageDirectory: packageDirectory,
testScript:
options.optionalString('test_script') ?? defaultOptions.testScript,
);
}
final String? outputDirectory;
final List<String> scopeOutput;
final bool functionCoverage;
final bool branchCoverage;
final String packageDirectory;
final String testScript;
}
class CoverageOptionsProvider {
CoverageOptionsProvider({String? filePath}) {
final file = _getOptionsFile(filePath);
final fileContents = file?.readAsStringSync();
// Pass null to fileContents if the file is empty
final options = Config.fromConfigFileContents(
fileContents: fileContents,
fileSourceUri: file?.uri,
);
coverageOptions = CoverageOptions.fromConfig(
options,
defaultOptions,
optionsFilePath,
);
}
late final CoverageOptions coverageOptions;
late final String? optionsFilePath;
static const defaultFilePath = 'coverage_options.yaml';
File? _getOptionsFile(String? filePath) {
filePath ??= findOptionsFilePath();
optionsFilePath = filePath != null
? path.normalize(path.absolute(filePath))
: null;
if (optionsFilePath == null) {
return null;
}
final file = File(optionsFilePath!);
return file.existsSync() ? file : null;
}
static String? findOptionsFilePath({Directory? directory}) {
var currentDir = directory ?? Directory.current;
while (true) {
final pubSpecFilePath = path.join(currentDir.path, 'pubspec.yaml');
if (File(pubSpecFilePath).existsSync()) {
final optionsFilePath = path.join(currentDir.path, defaultFilePath);
if (File(optionsFilePath).existsSync()) {
return optionsFilePath;
} else {
return null;
}
}
final parentDir = currentDir.parent;
if (parentDir.path == currentDir.path) {
return null;
}
currentDir = parentDir;
}
}
static const defaultOptions = CoverageOptions(
outputDirectory: null,
scopeOutput: [],
functionCoverage: false,
branchCoverage: false,
packageDirectory: '.',
testScript: 'test',
);
}